LeetCode:秒杀题 II

博客汇总了多道LeetCode算法题,包括整数与罗马数字互转、文本左右对齐、矩阵置零等题目。其中文本左右对齐题需用贪心算法,部分题要求原地修改数组、使用O(1)额外空间,涵盖多种算法类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

12,整数转罗马数字

题目:给你一个整数,将其转为罗马数字。

class Solution {
    public String intToRoman(int num) {
        int a1 = num / 1000;
        int b1 = num % 1000;
        int a2 = b1 / 500;
        int b2 = b1 % 500;
        int a3 = b2 / 100;
        int b3 = b2 % 100;
        int a4 = b3 / 50;
        int b4 = b3 % 50;
        int a5 = b4 / 10;
        int b5 = b4 % 10;
        int a6 = b5 / 5;
        int b6 = b5 % 5;
        String result = "";
        if (a1 != 0) {
            for (int i = 0; i < a1; i++) {
                result += "M";
            }
        }
        if (a2 != 0) {
            result += "D";
        }
        if (a3 != 0) {
            if (a3 == 4) {
                result += "CD";
            } else {
                for (int i = 0; i < a3; i++) {
                    result += "C";
                }
            }
        }
        if (a4 != 0) {
            result += "L";
        }
        if (a5 != 0) {
            if (a5 == 4) {
                result += "XL";
            } else {
                for (int i = 0; i < a5; i++) {
                    result += "X";
                }
            }
        }
        if (a6 != 0) {
            result += "V";
        }
        if (b6 != 0) {
            if (b6 == 4) {
                result += "IV";
            } else {
                for (int i = 0; i < b6; i++) {
                    result += "I";
                }
            }
        }
        String f = "";
        if (result.length() >= 3) {
            int i =0;
            for (; i < result.length() - 2; ) {
                String middle = result.substring(i, i + 3);
                if (middle.equals("DCD")) {
                    f += "CM";
                    i += 3;
                } else if (middle.equals("LXL")) {
                    f += "XC";
                    i += 3;
                } else if (middle.equals("VIV")) {
                    f += "IX";
                    i += 3;
                } else {
                    f += result.charAt(i);
                    i += 1;
                }
            }
            for (; i < result.length(); i++) {
                f += result.charAt(i);
            }
        } else {
            f = result;
        }
        return f;
    }
}

13,罗马数字转整数

题目:给定一个罗马数字,将其转换成整数。

class Solution {
    public int romanToInt(String s) {
        int result = 0;
        s=s.replaceAll("IV", "A");
        s=s.replaceAll("IX", "B");
        s=s.replaceAll("XL", "O");
        s=s.replaceAll("XC", "N");
        s=s.replaceAll("CD", "E");
        s=s.replaceAll("CM", "F");
        for (int i = 0; i < s.length(); i++) {
            String temp = String.valueOf(s.charAt(i));
            switch (temp){
                case "I":result+=1;break;
                case "V":result+=5;break;
                case "X":result+=10;break;
                case "L":result+=50;break;
                case "C":result+=100;break;
                case "D":result+=500;break;
                case "M":result+=1000;break;
                case "A":result+=4;break;
                case "B":result+=9;break;
                case "O":result+=40;break;
                case "N":result+=90;break;
                case "E":result+=400;break;
                case "F":result+=900;break;
            }
        }
        return result; 
    }
}

68,文本左右对齐

题目:给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

注意:

  • 单词是指由非空格字符组成的字符序列。
  • 每个单词的长度大于 0,小于等于 maxWidth
  • 输入单词数组 words 至少包含一个单词。
class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
        List<String> ans = new ArrayList<String>();
        int right = 0, n = words.length;
        while (true) {
            int left = right; // 当前行的第一个单词在 words 的位置
            int sumLen = 0; // 统计这一行单词长度之和
            // 循环确定当前行可以放多少单词,注意单词之间应至少有一个空格
            while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {
                sumLen += words[right++].length();
            }

            // 当前行是最后一行:单词左对齐,且单词之间应只有一个空格,在行末填充剩余空格
            if (right == n) {
                StringBuffer sb = join(words, left, n, " ");
                sb.append(blank(maxWidth - sb.length()));
                ans.add(sb.toString());
                return ans;
            }

            int numWords = right - left;
            int numSpaces = maxWidth - sumLen;

            // 当前行只有一个单词:该单词左对齐,在行末填充剩余空格
            if (numWords == 1) {
                StringBuffer sb = new StringBuffer(words[left]);
                sb.append(blank(numSpaces));
                ans.add(sb.toString());
                continue;
            }

            // 当前行不只一个单词
            int avgSpaces = numSpaces / (numWords - 1);
            int extraSpaces = numSpaces % (numWords - 1);
            StringBuffer sb = new StringBuffer();
            sb.append(join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1))); // 拼接额外加一个空格的单词
            sb.append(blank(avgSpaces));
            sb.append(join(words, left + extraSpaces + 1, right, blank(avgSpaces))); // 拼接其余单词
            ans.add(sb.toString());
        }
    }

    // blank 返回长度为 n 的由空格组成的字符串
    public String blank(int n) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < n; ++i) {
            sb.append(' ');
        }
        return sb.toString();
    }

    // join 返回用 sep 拼接 [left, right) 范围内的 words 组成的字符串
    public StringBuffer join(String[] words, int left, int right, String sep) {
        StringBuffer sb = new StringBuffer(words[left]);
        for (int i = left + 1; i < right; ++i) {
            sb.append(sep);
            sb.append(words[i]);
        }
        return sb;
    }
}

73,矩阵置零

题目:给定一个 m x n 的矩阵,如果一个元素为 ,则将其所在行和列的所有元素都设为 0 。

class Solution {
    public void setZeroes(int[][] matrix) {
        ArrayList a = new ArrayList();
        int row = matrix.length;
        int col = matrix[0].length;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (matrix[i][j] == 0) {
                    a.add(new int[]{i, j});
                }
            }
        }
        for (int i = 0; i < a.size(); i++) {
            int[] temp = (int[]) a.get(i);
            for (int n = 0; n < col; n++) {
                matrix[temp[0]][n] = 0;
            }
            for (int m = 0; m < row; m++) {
                matrix[m][temp[1]] = 0;
            }
        }
    }
}

80,删除有序数组中的重复项 II

题目:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

class Solution {
    public int removeDuplicates(int[] nums) {
        int temp = nums[0];
        int result = nums.length;
        int count = 1;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == temp && nums[i] != 1000000) {
                count++;
                if (count >= 3) {
                    for (int j = i - 1; j < nums.length - 1; j++) {
                        nums[j] = nums[j + 1];
                    }
                    nums[nums.length - 1] = 1000000;
                    i--;
                    result--;
                    count--;
                }
            } else {
                temp = nums[i];
                count = 1;
            }
        }
        return result;
    }
}

289,生命游戏

题目:根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。

给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

  1. 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
  2. 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
  3. 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
  4. 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。

class Solution {
    int[] dx = new int[]{1, 1, -1, -1, 0, 0, 1, -1};
    int[] dy = new int[]{1, -1, 1, -1, 1, -1, 0, 0};

    public void gameOfLife(int[][] board) {
        int heigh = board.length;
        int width = board[0].length;
        ArrayList<Integer[]> arrayList = new ArrayList<Integer[]>();
        for (int i = 0; i < heigh; i++) {
            for (int j = 0; j < width; j++) {
                int alive = 0;
                for (int k = 0; k < dx.length; k++) {
                    int newX = i + dx[k];
                    int newY = j + dy[k];
                    if (newX >= 0 && newX < heigh && newY >= 0 && newY < width && board[newX][newY] == 1) {
                        alive++;
                    }
                }
                if (alive < 2 && board[i][j] == 1) {
                    //细胞死亡
                } else if ((alive == 2 || alive == 3) && board[i][j] == 1) {
                    arrayList.add(new Integer[]{i, j});
                } else if (alive > 3 && board[i][j] == 1) {
                    //细胞死亡
                } else if (alive == 3 && board[i][j] == 0) {
                    arrayList.add(new Integer[]{i, j});
                }
            }
        }
        for (int i = 0; i < heigh; i++) {
            for (int j = 0; j < width; j++) {
                board[i][j] = 0;
            }
        }
        for (int i = 0; i < arrayList.size(); i++) {
            Integer[] temp = arrayList.get(i);
            board[temp[0]][temp[1]] = 1;
        }
    }
}

299,猜数字游戏

题目:你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下:写出一个秘密数字,并请朋友猜这个数字是多少。朋友每猜测一次,你就会给他一个包含下述信息的提示:猜测数字中有多少位属于数字和确切位置都猜对了(称为 "Bulls",公牛),有多少位属于数字猜对了但是位置不对(称为 "Cows",奶牛)。也就是说,这次猜测中有多少位非公牛数字可以通过重新排列转换成公牛数字。

给你一个秘密数字 secret 和朋友猜测的数字 guess ,请你返回对朋友这次猜测的提示。提示的格式为 "xAyB" ,x 是公牛个数, y 是奶牛个数,A 表示公牛,B 表示奶牛。请注意秘密数字和朋友猜测的数字都可能含有重复数字。

class Solution {
    public String getHint(String secret, String guess) {
        int a = 0;
        int b = 0;
        ArrayList arrayList = new ArrayList();
        ArrayList<String> t = new ArrayList();
        for (int i = 0; i < secret.length(); i++) {
            if (secret.charAt(i) == guess.charAt(i)) {
                a++;
                arrayList.add(i);
            } else {
                t.add(secret.charAt(i)+"");
            }
        }
        for (int i = 0; i < guess.length(); i++) {
            if (!arrayList.contains(i)) {
                char c = guess.charAt(i);
                if (t.contains(c+"")) {
                    t.remove(c+"");
                    b++;
                }
            }
        }
        return a + "A" + b + "B";
    }
}

344:反转字符串

题目:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

class Solution {
    public void reverseString(char[] s) {
        int left = 0;
        int right = s.length - 1;
        char temp = 0;
        while (left <= right) {
            temp = s[right];
            s[right] = s[left];
            s[left] = temp;
            left++;
            right--;
            if (left==right){
                break;
            }
        }
    }
}

509,斐波那契数

题目:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

class Solution {
    public int fib(int n) {
        int a = 0;
        int b = 1;
        if (n == 0) {
            return a;
        }
        if (n == 1) {
            return b;
        }
        int c = 0;
        for (int i = 2; i <= n; i++) {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
}

557:反转字符串中的单词III

题目:给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

class Solution {
    public String reverseWords(String s) {
        String[] t = s.split(" ");
        String result = "";
        for (int i = 0; i < t.length; i++) {
            if (i == t.length - 1) {
                result += reverseString(t[i]);
            } else {
                result += reverseString(t[i]) + " ";
            }
        }
        return result;
    }
    public String reverseString(String string) {
        char[] s = string.toCharArray();
        int left = 0;
        int right = s.length - 1;
        char temp = 0;
        while (left <= right) {
            temp = s[right];
            s[right] = s[left];
            s[left] = temp;
            left++;
            right--;
            if (left == right) {
                break;
            }
        }
        return String.valueOf(s);
    }
}

807,保持城市天际线

题目:给你一座由 n x n 个街区组成的城市,每个街区都包含一座立方体建筑。给你一个下标从 0 开始的 n x n 整数矩阵 grid ,其中 grid[r][c] 表示坐落于 r 行 c 列的建筑物的 高度 。

城市的 天际线 是从远处观察城市时,所有建筑物形成的外部轮廓。从东、南、西、北四个主要方向观测到的 天际线 可能不同。

我们被允许为 任意数量的建筑物 的高度增加 任意增量(不同建筑物的增量可能不同) 。 高度为 0 的建筑物的高度也可以增加。然而,增加的建筑物高度 不能影响 从任何主要方向观察城市得到的 天际线 。

在 不改变 从任何主要方向观测到的城市 天际线 的前提下,返回建筑物可以增加的 最大高度增量总和 。

class Solution {
    public int maxIncreaseKeepingSkyline(int[][] grid) {
        int length = grid.length;
        int result = 0;
        int[] maxRow = new int[length];
        int[] maxCol = new int[length];
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {
                maxRow[i] = Math.max(grid[i][j], maxRow[i]);
                maxCol[j] = Math.max(grid[i][j], maxCol[j]);
            }
        }
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {
                result += Math.min(maxCol[j] - grid[i][j], maxRow[i] - grid[i][j]);
            }
        }
        return result;
    }
}

1046,最后一块石头的重量

题目:有一堆石头,每块石头的重量都是正整数。每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0

class Solution {
    public int lastStoneWeight(int[] stones) {
         PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
            public int compare(Integer m, Integer n) {
                return n - m;
            }
        });
        for (int x : stones) {
            queue.add(x);
        }
        while (queue.size() != 1) {
            queue.add(queue.poll() - queue.poll());
        }
        return queue.poll();
    }
}

1480,一维数组的动态和

题目:给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。请返回 nums 的动态和。

class Solution {
    public int[] runningSum(int[] nums) {
        int length = nums.length;
        int[] result = new int[length];
        result[0] = nums[0];
        for (int i = 1; i < length; i++) {
            result[i] = result[i - 1] + nums[i];
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕双嘤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值