数组和字符串

数组简介

1. LeetCode 1991 找到数组的中间位置

方法1:前缀和

class Solution {
    public int findMiddleIndex(int[] nums) {
        int tol = 0, s = 0;
        for(int num : nums) 
            tol += num;
        for(int i = 0; i < nums.length; i++) {
            if(s == tol - s - nums[i])
                return i;
            s += nums[i];
        }
        return -1;
    }
}

2. LeetCode 35 搜索插入位置

方法1:二分查找

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length;
        while(left < right) {
            int mid = (left + right) >> 1;
            if(nums[mid] < target)
                left = mid + 1;
            else
                right = mid;
        }
        return left;
    }
}

3. LeetCode 56 合并区间

方法1:贪心

  • 排序 (a, b) -> a[0] - b[0]
  • 列表转数组 toArray(new int[M][N])
class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        List<int []> ans = new ArrayList<int []>();
        for(int[] info : intervals) {
            int n = ans.size(), left = info[0], right = info[1];
            // 数组为空 或 区间不能合并
            if(n == 0 || ans.get(n - 1)[1] < left)
                ans.add(info);
            else // 进行合并区间
                ans.get(n - 1)[1] = Math.max(ans.get(n - 1)[1], right);
        }
        return ans.toArray(new int[ans.size()][2]);
    }
}
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x: x[0])
        ans = list()
        for (left, right) in intervals:
            # 列表为空 或 区间不能合并
            if not ans or ans[-1][1] < left:
                ans.append([left, right])
            else: # 区间可以合并
                ans[-1][1] = max(ans[-1][1], right)
        return ans

二维数组简介

1. LeetCode 48 旋转图像

方法1:辅助数组

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int[][] temp = new int[n][n];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) 
                temp[i][j] = matrix[n - 1 - j][i];
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) 
                matrix[i][j] = temp[i][j];
        }
    }
}

2. LeetCode 73 矩阵置零

方法1:标记数组

class Solution {
    public void setZeroes(int[][] matrix) {
        int n = matrix.length, m = matrix[0].length;
        boolean[] row = new boolean[n];
        boolean[] col = new boolean[m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(matrix[i][j] == 0) {
                    row[i] = true; col[j] = true;
                }
            }
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(row[i] || col[j])
                    matrix[i][j] = 0;
            }
        }
    }
}

3. LeetCode 498 对角线遍历

方法1:模拟

class Solution {
    public int[] findDiagonalOrder(int[][] mat) {
        int m = mat.length, n = mat[0].length, k = 0;
        int[] ans = new int[m * n];
        for(int i = 0; i < m + n - 1; i++) {
            if(i % 2 == 0) {  // 从下往上 x(-1) y(+1)
                int x = Math.min(i, m - 1);
                int y = Math.max(0, i - m + 1);
                while(x >= 0 && y < n)  // 边界
                    ans[k++] = mat[x--][y++];
            } else {  // 从上往下 x(+1) y(-1)
                int x = Math.max(0, i - n + 1);
                int y = Math.min(i, n - 1);
                while(x < m && y >= 0)
                    ans[k++] = mat[x++][y--];
            }
        }
        return ans;
    }
}

字符串简介

1. LeetCode 14 最长公共前缀

方法1:横向扫描

class Solution {
    public String longestCommonPrefix(String[] strs) {
        String prefix = strs[0];  // 默认前缀
        for(int i = 1; i < strs.length; i++) {
            // 求每个字符串与 prefix 的最长前缀
            prefix = commonPrefix(prefix, strs[i]);
            if(prefix == "") return prefix;  // 进行提前剪枝
        }
        return prefix;
    }

    static String commonPrefix(String str1, String str2) {
        int length = Math.min(str1.length(), str2.length());
        for(int i = 0; i < length; i++) {
            if(str1.charAt(i) != str2.charAt(i))
                return str1.substring(0, i);
        }
        return str1.substring(0, length);  // 全部匹配上
    }
}

方法2:纵向扫描

class Solution {
    public String longestCommonPrefix(String[] strs) {
        int length = strs[0].length(), count = strs.length;
        for(int i = 0; i < length; i++) {
            // strs[0] 的第 i 位是否出现后面字符串的第 i 位
            char c = strs[0].charAt(i);
            for(int j = 1; j < count; j++) {
                if(i == strs[j].length() || c != strs[j].charAt(i))
                    return strs[0].substring(0, i);
            }
        }
        return strs[0];
    }
}

2. LeetCode 5 最长回文子串

方法1:动态规划

class Solution {
    public String longestPalindrome(String s) {
        // 记录回文串的最长长度和起始位置
        int maxLen = 1, begin = 0, n = s.length();
        // dp[i][j] 表示 s[i ~ j] 是否是回文串
        boolean[][] dp = new boolean[n][n];
        // 长度为 1 的字符是回文串
        for(int i = 0; i < n; i++) 
            dp[i][i] = true;
        for(int L = 2; L <= n; L++) { // 枚举子串的长度
            for(int i = 0; i < n; i++) { // 枚举左边界
                int j = i + L - 1; // 右边界
                if(j >= n) break;
                if(s.charAt(i) == s.charAt(j)) {
                    if(i + 1 == j) // 两个相同字符相邻
                        dp[i][j] = true;
                    else // 当前是否是回文串取决于 s[i+1 ~ j-1]
                        dp[i][j] = dp[i + 1][j - 1];
                } else { // s[i ~ j] 不是回文串
                    dp[i][j] = false;
                }
                if(dp[i][j] && j - i + 1 > maxLen) {
                    // 更新字符串长度和起始位置
                    maxLen = j - i + 1; begin = i;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }
}

3. Leetcode 151 反转字符串中的单词

方法1:自带函数

class Solution {
    public String reverseWords(String s) {
        s = s.trim(); // 除去开头和末尾的空白字符
        // 正则匹配连续的空白字符作为分隔符
        List<String> wordList = Arrays.asList(s.split("\\s+"));
        Collections.reverse(wordList);
        return String.join(" ", wordList);
    }
}
class Solution:
    def reverseWords(self, s: str) -> str:
        return " ".join(reversed(s.split()))

双指针技巧

1. LeetCode 344 反转字符串

方法1:双指针

class Solution {
    public void reverseString(char[] s) {
        for(int i = 0, j = s.length - 1; i < j; i++, j--) {
            char temp = s[i]; s[i] = s[j]; s[j] = temp;
        }
    }
}

2. LeetCode 561 数组拆分

方法1:贪心

class Solution {
    public int arrayPairSum(int[] nums) {
        Arrays.sort(nums);
        int ans = 0;
        for(int i = 0; i < nums.length; i += 2)
            ans += nums[i];
        return ans;
    }
}

3. LeetCode 1 两数之和

方法1:暴力

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for(int i = 0; i < n - 1; i++) {
            for(int j = i + 1; j < n; j++) {
                if(nums[i] + nums[j] == target)
                    return new int[]{i, j};
            }
        }
        return new int[0];
    }
}

方法2:哈希表

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
        for(int i = 0; i < nums.length; i++) {
            if(hashtable.containsKey(target - nums[i]))
                return new int[]{hashtable.get(target - nums[i]), i};
            hashtable.put(nums[i], i);
        }
        return new int[0];
    }
}

4. LeetCode 27 移除元素

方法1:快慢指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int n = nums.length, slow = 0;
        for(int fast = 0; fast < n; fast++) {
            if(nums[fast] != val) // 需要将此时的数字保存下来
                nums[slow++] = nums[fast];
        }
        return slow;
    }
}

方法2:左右指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0, right = nums.length - 1;
        while(left <= right) { // 当两指针相遇时仍需要判定
            if(nums[left] == val) // 需要删除nums[left]
                nums[left] = nums[right--];
            else // 保存nums[left]
                left++;
        }
        return left;
    }
}

5. LeetCode 485 最大连续1的个数

方法1:模拟

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int ans = 0, cnt = 0;
        for(int i = 0; i <= nums.length; i++) {
            if(i == nums.length || nums[i] == 0) { 
                ans = Math.max(ans, cnt); cnt = 0;
            } else
                cnt++;
        }
        return ans;
    }
}

6. LeetCode 209 长度最小的子数组

方法1:滑动窗口

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        int left = 0, right = 0, val = 0, ans = n + 1;
        while(right < n) {
            val += nums[right++];
            while(val >= target) {
                ans = Math.min(ans, right - left);
                val -= nums[left++];
            }
        }
        return ans == n + 1 ? 0 : ans;
    }
}

小结

1. LeetCode 118 杨辉三角

方法1:数学

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        for(int i = 0; i < numRows; i++) {
            List<Integer> temp = new ArrayList<Integer>();
            for(int j = 0; j <= i; j++) {
                if(j == 0 || j == i)
                    temp.add(1);
                else
                    temp.add(ans.get(i - 1).get(j - 1) + ans.get(i - 1).get(j));
            }
            ans.add(temp);
        }
        return ans;
    }
}

2. LeetCode 119 杨辉三角II

方法1:递推

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> ans = new ArrayList<Integer>();
        ans.add(1); // 初始化
        for(int i = 1; i <= rowIndex; i++) {
            ans.add(0); // 下一列比上一列多一个元素
            for(int j = i; j > 0; j--) // 倒序遍历 避免数据覆盖
                ans.set(j, ans.get(j - 1) + ans.get(j));
        }
        return ans;
    }
}

方法2:线性递推

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> ans = new ArrayList<Integer>();
        ans.add(1); // 初始化
        for(int i = 1; i <= rowIndex; i++) {
            // C(m, n) = C(m - 1, n) * (n - m + 1) / m;
            long res = (long)ans.get(i - 1) * (rowIndex - i + 1);
            ans.add((int)(res / i));
        }
        return ans;
    }
}

3. LeetCode 557 反转字符串中的单词III

4. LeetCode 153 寻找旋转排序数组中的最小值

方法1:二分查找

class Solution {
    public int findMin(int[] nums) {
        // 左边升序 右边升序 左边最小值 > 右边最大值
        int low = 0, high = nums.length - 1;
        while(low < high) {
            int mid = (low + high) >> 1;
            if(nums[mid] < nums[high]) // 在右边
                high = mid; // mid ... right 升序
            else // 在左边
                low = mid + 1;
        }
        return nums[low];
    }
}

5. LeetCode 26 删除有序数组中的重复项

方法1:双指针

class Solution {
    public int removeDuplicates(int[] nums) {
        int slow = 1;
        for(int fast = 1; fast < nums.length; fast++) {
            if(nums[fast] != nums[fast - 1])
                nums[slow++] = nums[fast];
        }
        return slow;
    }
}

6. LeetCode 283 移动零

方法1:双指针

class Solution {
    public void moveZeroes(int[] nums) {
        int slow = 0;
        for(int fast = 0; fast < nums.length; fast++) {
            if(nums[fast] != 0) {
                int temp = nums[slow];
                nums[slow++] = nums[fast];
                nums[fast] = temp;
            }
        }
    }
}
posted @   Koonan-Edogawa  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示