Leetcode面试经典150题

数组字符串

合并两个有序数组

思路

类似于归并排序,对两个有序数组进行合并即可,但是空间复杂度是O(n+m);

代码

java 复制代码
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] ans = new int[n + m];
        int i = 0, j = 0;
        int cnt = 0;
        while (i < m && j < n) {
            if (nums1[i] < nums2[j]) {
                ans[cnt++] = nums1[i++];
            } else {
                ans[cnt++] = nums2[j++];
            }
        }
        while(i < m) ans[cnt++] = nums1[i++];
        while(j < n) ans[cnt++] = nums2[j++];
        for (int k = 0; k < cnt; ++k) {
            nums1[k] = ans[k];
        }
    }
}

优化:有一点小优化吧,可以从后往前合并装入nums1的后面,这样不会影响nums1的元素,同样也节省了n+m的空间(本题的数据量小,所以看不出)。

java 复制代码
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1;
        int j = n - 1;
        int cnt = n + m - 1;
        while(i >= 0 && j >= 0) {
            if (nums1[i] < nums2[j]) {
                nums1[cnt--] = nums2[j--];
            } else {
                nums1[cnt--] = nums1[i--];
            }
        }
        while(i >= 0) nums1[cnt--] = nums1[i--];
        while(j >= 0) nums1[cnt--] = nums2[j--];
    }
}

双指针

验证回文串

思路

用头指针和尾指针,每次比较的时候必须满足两个指针指向的是数字或字符,其他的符号都跳过。

代码

java 复制代码
class Solution {
    public boolean isPalindrome(String s) {
        s = s.toLowerCase();
        int len = s.length();
        int i = 0, j = len - 1;
        char[] ch = s.toCharArray();
        while(i < j) {
            while(i < len && !check(ch[i])) ++i;
            while(j >= 0 && !check(ch[j])) --j;//前面两句是过滤非字符或数字
            if (i > j) {
                break;
            }
            if (ch[i] >= 'a') {
                ch[i] -= 32;
            }
            if (ch[j] >= 'a') {
                ch[j] -= 32;
            }// 如果是字符,则统一转为小写
            if (ch[i] != ch[j]) {
                return false;
            }
            ++i;
            --j;
        }
        return true;
    }
    private boolean check(char ch) {
        if (ch <= 'z' && ch >= 'a') {
            return true;
        }
        if (ch <= 'Z' && ch >= 'z') {
            return true;
        }
        if (ch <= '9' && ch >= '0') {
            return true;
        }
        return false;
    }
}

滑动窗口

长度最小的子数组

思路

由滑动窗口思想:设两个指针,尾指针一直走,当满足某个条件时,头指针也跟着走。

条件:当子数组和大于target时,不断缩小窗口,找到最小的窗口。

代码

java 复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int ans = nums.length;
        int ind = 0;
        int sum = 0;
        for (int i = 0; i < nums.length; ++i) {
            sum += nums[i];
            while (sum >= target) {
                sum -= nums[ind];
                ans = Math.min(ans, i - ind + 1);
                ind++;
            }
        }
        if (ind == 0) { // sum>=target没有执行,不存在子数组
            return 0;
        } 
        return ans;
    }
}

矩阵

有效的数独

思路

创建三个set数组,分别是对存"行","列","区域"的数字,如果对应的set中有值,那么就不是有效的。否则就添加

这里最主要的是怎样判断是否为同一个区域。

可以先对9x9的表格通过i/3,j/3划分为9个3x3区域然后每个区域的值都是

(0, 0), (0, 1), (0, 2)

(1, 0), (1, 1)...

再通过将二维数组变为一维数组的计算公式i * row + j。就是9个区域。

代码

java 复制代码
class Solution {
    public boolean isValidSudoku(char[][] board) {
        Set<Character>[] rows = new HashSet[9];
        Set<Character>[] cols = new HashSet[9];
        Set<Character>[] area = new HashSet[9];
        for (int i = 0; i < 9; ++i) {
            rows[i] = new HashSet<>();
            cols[i] = new HashSet<>();
            area[i] = new HashSet<>();
        }
        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if (board[i][j] > '9' || board[i][j] < '0') continue;
                if (rows[i].contains(board[i][j])) {
                    return false;
                } else {
                    rows[i].add(board[i][j]);
                }

                if (cols[j].contains(board[i][j])) {
                    return false;
                } else {
                    cols[j].add(board[i][j]);
                }
                int t= i / 3 * 3 + j / 3;
                //System.out.println(i + " " + j + " " + t);
                if (area[t].contains(board[i][j])) {
                    return false;
                } else {
                    area[t].add(board[i][j]);
                }
            }
        }
        return true;
    }
}

哈希表

赎金信

思路

比较r和m的26个字符个数,如果r的某个字符个数大于m的某个字符个数,则r不能由m的字符组成。

代码

java 复制代码
class Solution {
    public boolean canConstruct(String r, String m) {
        int[] rCnt = new int[26];
        int[] mCnt = new int[26];
        for (int i = 0; i < r.length(); ++i) {
            rCnt[r.charAt(i) - 'a']++;
        }
        for (int i = 0; i < m.length(); ++i) {
            mCnt[m.charAt(i) - 'a']++;
        }
        for (int i = 0; i < 26; ++i) {
            if (rCnt[i] > mCnt[i]) {
                return false;
            }
        }
        return true;
    }
}
相关推荐
m0_571957582 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
pianmian14 小时前
python数据结构基础(7)
数据结构·算法
好奇龙猫6 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20247 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸7 小时前
链表的归并排序
数据结构·算法·链表
jrrz08287 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time7 小时前
golang学习2
算法
南宫生8 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步9 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara9 小时前
函数对象笔记
c++·算法