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;
    }
}
相关推荐
森焱森1 小时前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
QuantumStack3 小时前
【C++ 真题】P1104 生日
开发语言·c++·算法
写个博客4 小时前
暑假算法日记第一天
算法
绿皮的猪猪侠4 小时前
算法笔记上机训练实战指南刷题
笔记·算法·pta·上机·浙大
hie988944 小时前
MATLAB锂离子电池伪二维(P2D)模型实现
人工智能·算法·matlab
杰克尼4 小时前
BM5 合并k个已排序的链表
数据结构·算法·链表
.30-06Springfield5 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦5 小时前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
xiaolang_8616_wjl5 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20
small_wh1te_coder5 小时前
硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
linux·c语言·汇编·嵌入式硬件·算法·c