[知识总结] 【CodeTop x LeetCode】Page 4 : 61-80面试高频算法题题解
作者:CC下载站 日期:2021-11-10 08:59:00 浏览:74 分类:编程开发
更多答案也可以关注我的GitHub算法仓库——Algorithm
所有代码都是在力扣上提交通过的,保证代码的正确无误
基础数据结构:
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
155.最小栈
使用 辅助栈,与元素栈同步插入与删除,用于存储与每个元素对应的最小值。
- 当一个元素要入栈时,我们取当前辅助栈的栈顶存储的最小值,与当前元素比较得出最小值,将这个最小值插入辅助栈中
- 当一个元素要出栈时,我们把辅助栈的栈顶元素也一并弹出
- 在任意一个时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中
class MinStack {
ArrayDeque<Integer> stack;
ArrayDeque<Integer> minStack;
public MinStack() {
stack = new ArrayDeque<>();
minStack = new ArrayDeque<>();
minStack.push(Integer.MAX_VALUE);
}
public void push(int val) {
stack.push(val);
minStack.push(Math.min(val, minStack.peekFirst()));
}
public void pop() {
stack.pop();
minStack.pop();
}
public int top() {
return stack.peekFirst();
}
public int getMin() {
return minStack.peekFirst();
}
}
41.缺失的第一个正数
缺失的正数一定在[1, nums.length+1]中,由于题目限制空间复杂度为O(1),我们需要修改原数组,结合数组下标的特性来替代哈希表。
public int firstMissingPositive(int[] nums) {
int l = nums.length;
//将所有小于等于0的数置为l+1
for (int i = 0; i < l; i++) {
if (nums[i] <= 0) {
nums[i] = l+1;
}
}
for (int i = 0; i < l; i++) {
int temp = Math.abs(nums[i]);
if (temp <= l) {
nums[temp-1] = -Math.abs(nums[temp-1]);
}
}
//寻找下标对应的第一个正数,返回该下标
for (int i = 0; i < l; i++) {
if (nums[i] > 0) {
return i+1;
}
}
return l+1;
}
718.最长重复子数组
这里要注意是连续子数组,不同于字符串的子序列,所以状态转移方程中不相等的情况下:dp[i][j] = 0;
- 动规:时间O(MN),空间O(MN)
- 滑动窗口: O((N+M)×min(N,M)) ,空间 O(1)
public int findLength(int[] nums1, int[] nums2) {
int[][] dp = new int[nums1.length+1][nums2.length+1];
int res = 0;
for (int i = 1; i <= nums1.length ; i++) {
for (int j = 1; j <= nums2.length; j++) {
if (nums1[i-1] == nums2[j-1]) {
dp[i][j] = 1 + dp[i-1][j-1];
} else {
dp[i][j] = 0;
}
res = Math.max(res, dp[i][j]);
}
}
return res;
}
234.回文链表
时间O(n),空间O(1),思路还是比较好想的
- 快慢指针找中点
- 翻转一半
- 再遍历比较
class Solution {
public boolean isPalindrome(ListNode head) {
if (head.next == null) {
return true;
}
ListNode slow = head, fast = head, slowPre = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slowPre = slow;
slow = slow.next;
}
ListNode l2 = slow.next, l1;
if (fast.next != null) {
slowPre = slow;
}
slowPre.next = null;
l1 = reverseList(head);
while (l1 != null && l2 != null) {
if (l1.val != l2.val) {
return false;
}
l1 = l1.next;
l2 = l2.next;
}
return true;
}
public ListNode reverseList(ListNode head) {
ListNode prev = null, next = null;
while (head != null) {
next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
}
78.子集
记原序列中元素的总数为 n。原序列中的每个数字 ai 的状态可能有两种,即「在子集中」和「不在子集中」。
我们用 1 表示「在子集中」,0 表示不在子集中,那么每一个子集可以对应一个长度为 n 的 0/1 序列,第 i 位表示 ai是否在子集中。
(这里会用到位运算)
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> t = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < (1 << n); i++) {
t.clear();
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) != 0) {
t.add(nums[j]);
}
}
res.add(new ArrayList<>(t));
}
return res;
}
112.路径总和
递归
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return sum == root.val;
}
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
}
98.验证二叉搜索树
两个递归思路:
- 递归,但要判断节点的上下界
- 递归,中序遍历需递增
class Solution {
Long last = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
if (isValidBST(root.left)) {
if (last < root.val) {
last = root.val + 0l;
return isValidBST(root.right);
}
}
return false;
}
}
32.最长有效括号
也是一道动态规划,但是动态规划的转移方程比较难想,dp[i]代表以s.charAt(i)结尾时的最长有效括号,由于题目要求为最长且连续,那么:
- 如果
dp[i] == '('
,那么在当前位置一定是0 - 如果
dp[i] == ')'
,那么需要根据dp[i-1]来找到前一个为被匹配的 '(' - 如果存在,则
dp[i] = 2 + dp[i-1] + dp[i - dp[i-1] - 2]
这里的dp[i - dp[i-1] - 2]
为上一个未被匹配的'(',也就是上一个断连之前的最长连续有效括号值 - 其中还需要判断数组下标-1的情况
public int longestValidParentheses(String s) {
int len = s.length();
if (len <= 1) {
return 0;
}
int res = 0;
int[] dp = new int[len];
for (int i = 1; i < len; i++) {
if (s.charAt(i) == ')' && i - dp[i-1] > 0 && s.charAt(i - dp[i-1] -1) == '(') {
dp[i] += (2 + dp[i-1]);
if (i - dp[i-1] > 1) {
dp[i] += dp[i - dp[i-1] - 2];
}
res = Math.max(res, dp[i]);
}
}
return res;
}
101.对称二叉树
两个指针,同步对称移动
class Solution {
public boolean isSymmetric(TreeNode root) {
return dfs(root, root);
}
public boolean dfs(TreeNode q, TreeNode p) {
if (q == null && p == null) {
return true;
}
if (q == null || p == null) {
return false;
}
return q.val == p.val && dfs(q.left, p.right) && dfs(q.right, p.left);
}
}
322.零钱兑换
区间dp,dp数组定义不是根据硬币,而是根据金额:dp[i] 代表总金额为 i 时所需的最小硬币个数
状态转移方程也是有些难度的,将数组初始化为无穷大,代表此金额无法使用所给金币凑出,dp[0] = 0
- 如果当前金额可以被某一种硬币凑出,则:
dp[i] = Math.min(dp[i - coin] + 1, dp[i]);
public int coinChange(int[] coins, int amount) {
if (amount == 0) {
return 0;
}
int[] dp = new int[amount+1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int coin : coins) {
for (int i = coin; i <= amount ; i++) {
if (dp[i - coin] != Integer.MAX_VALUE) {
dp[i] = Math.min(dp[i - coin] + 1, dp[i]);
}
}
}
return dp[amount] < Integer.MAX_VALUE ? dp[amount] : -1;
}
22.括号生成
题目要求给出所有可能,暴力dfs即可
class Solution {
List<String> res = new ArrayList<>();
public List<String> generateParenthesis(int n) {
dfs(n, n, "");
return res;
}
public void dfs(int left, int right, String s) {
for (int i = 0; i < 2; i++) {
if (left == 0 && right == 0) {
res.add(s);
break;
}
if (i == 0 && left > 0) {
dfs(left - 1, right, s + "(");
}else if (i == 1 && right > left) {
dfs(left, right - 1, s + ")");
}
}
}
}
169.多数元素
Boyer-Moore 投票算法,时间O(n),空间O(1)
算法过程:
我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予candidate,随后我们判断 x:
- 如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
- 如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
在遍历完成后,candidate 即为整个数组的众数。
投票算法证明:
- 如果候选人不是maj 则 maj,会和其他非候选人一起反对 会反对候选人,所以候选人一定会下台(maj==0时发生换届选举)
- 如果候选人是maj , 则maj 会支持自己,其他候选人会反对,同样因为maj 票数超过一半,所以maj 一定会成功当选
public int majorityElement(int[] nums) {
int cand = 0, count = 0;
for (int i = 0; i < nums.length; i++) {
if (count == 0) {
cand = nums[i];
}
count += (cand == nums[i] ? 1 : -1);
}
return cand;
}
48.旋转图像
原地旋转:将矩形分为四块,两个for循环一块的量,但是每次swap四个块的坐标
就是四个对应坐标的转换方程有些难推
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < (n+1)/2; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;
}
}
}
43.字符串相乘
很恶心的题,费劲又麻烦,没啥特别简洁的套路
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
int[] res = new int[num1.length() + num2.length()];
for (int i = num1.length() - 1; i >= 0; i--) {
int n1 = num1.charAt(i) - '0';
for (int j = num2.length() - 1; j >= 0; j--) {
int n2 = num2.charAt(j) - '0';
int sum = (res[i + j + 1] + n1 * n2);
res[i + j + 1] = sum % 10;
res[i + j] += sum / 10;
}
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < res.length; i++) {
if (i == 0 && res[i] == 0) continue;
result.append(res[i]);
}
return result.toString();
}
64.最小路径和
很简单常规的二维dp,转移方程 dp[i][j] = grid[i][j] + Math.min(dp[i][j-1], dp[i-1][j])
public int minPathSum(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
int[][] dp = new int[row][col];
dp[0][0] = grid[0][0];
for (int i = 1; i < row; i++) {
dp[i][0] = dp[i-1][0] + grid[i][0];
}
for (int i = 1; i < col; i++) {
dp[0][i] = dp[0][i-1] + grid[0][i];
}
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
dp[i][j] = grid[i][j] + Math.min(dp[i][j-1], dp[i-1][j]);
}
}
return dp[row-1][col-1];
}
226. 翻转二叉树
典型递归
public TreeNode invertTree(TreeNode root) {
if (root != null) {
invertTree(root.left);
invertTree(root.right);
TreeNode tree = root.left;
root.left = root.right;
root.right = tree;
}
return root;
}
165.比较版本号
String.split分割,但是注意特殊字符前加\
class Solution {
public int compareVersion(String version1, String version2) {
String[] s1 = version1.split("\.");
String[] s2 = version2.split("\.");
int len1 = s1.length;
int len2 = s2.length;
for (int i = 0; i < len1 && i < len2; i++) {
if (Integer.valueOf(s1[i]) > Integer.valueOf(s2[i])) {
return 1;
}
if (Integer.valueOf(s1[i]) < Integer.valueOf(s2[i])) {
return -1;
}
}
if (len1 > len2 && remain(s1, len2) > 0) {
return 1;
}else if (len1 < len2 && remain(s2, len1) > 0) {
return -1;
}
return 0;
}
public int remain(String[] arr, int start) {
StringBuilder sb = new StringBuilder("");
for (int i = start; i < arr.length; i++) {
sb.append(arr[i]);
}
return Integer.valueOf(sb.toString());
}
}
34.在排序数组中查找元素的第一个和最后一个位置
在使用二分查找第一次查找到目标值之后继续二分查找
那么第一次出现的即为一直二分后最左的位置,最后一次出现即为第一次比target大的数的下标-1
class Solution {
public int[] searchRange(int[] nums, int target) {
int leftIdx = binarySearch(nums, target, true);
int rightIdx = binarySearch(nums, target, false) - 1;
if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target) {
return new int[]{leftIdx, rightIdx};
}
return new int[]{-1, -1};
}
public int binarySearch(int[] nums, int target, boolean lower) {
int left = 0, right = nums.length - 1, ans = nums.length;
while (left <= right) {
int mid = (left + right)/2;
if (nums[mid] > target || (lower && nums[mid] >= target)) {
right = mid -1;
ans = mid;
} else {
left = mid + 1;
}
}
return ans;
}
}
83.删除排序链表中的重复元素
链表基操
public ListNode deleteDuplicates(ListNode head) {
ListNode node = head;
while (node != null) {
ListNode cur = node.next;
while (cur != null && node.val == cur.val) {
cur = cur.next;
}
node.next = cur;
node = node.next;
}
return head;
}
39.组合总和
由于题目要求所有情况,暴力dfs + 剪枝 + 回溯 即可
class Solution {
List<List<Integer>> res = new ArrayList<>();
int[] arr;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
arr = candidates;
dfs(new ArrayList<>(), target, 0);
return res;
}
public void dfs(List<Integer> list, int val, int index) {
if (val < 0) {
return;
}
if (val == 0) {
res.add(new ArrayList<>(list));
}
for (int i = index; i < arr.length; i++) {
list.add(arr[i]);
dfs(list, val - arr[i], i);
list.remove(list.size() - 1);
}
}
}
猜你还喜欢
- 03-29 [编程相关] Winform窗体圆角以及描边完美解决方案
- 03-29 [前端问题] has been blocked by CORS policy跨域问题解决
- 03-29 [编程相关] GitHub Actions 入门教程
- 03-29 [编程探讨] CSS Grid 网格布局教程
- 10-12 [编程相关] python实现文件夹所有文件编码从GBK转为UTF8
- 10-11 [编程算法] opencv之霍夫变换:圆
- 10-11 [编程算法] OpenCV Camshift算法+目标跟踪源码
- 10-11 [Python] python 创建 Telnet 客户端
- 10-11 [编程相关] Python 基于 Yolov8 + CPU 实现物体检测
- 03-15 [脚本工具] 使用go语言开发自动化脚本 - 一键定场、抢购、预约、捡漏
- 01-08 [编程技术] 秒杀面试官系列 - Redis zset底层是怎么实现的
- 01-05 [编程技术] 《Redis设计与实现》pdf
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[美剧] 史密斯夫妇.2024.8集全.4K.附影版
[电影] 最佳拍档5:兵马俑风云(含前4部全合集)[喜剧/动作/犯罪]
[有声小说] 《都市风水师》 作者:听叶 主播:原野 434集完【MP3】
[电影] 重启2000之传奇人生(84集)
[有声小说] 《百炼成神》 主播:令狐笑笑生&浥轻尘 3913集完【MP3】 [40.3G]
[有声小说] 《傲世九重天》 作者:风凌天下 主播:我影随风 2323集完结【MP3】
[美剧] 《女巫阿加莎》2024 [1080P BD][英语 中英双语字幕][1-9集全]
[美剧] 企鹅人 The Penguin (2024) 1080P 全8集完结
[电视剧] 我们在黑夜中相拥 (2024) 1080 横屏短剧 更24完结
[书籍] 经典科普书籍合集30套近300部·完美精校全插图收藏版
[书籍] 彭子益医书合集 [PDF/DOC]
[游戏] 《黑神话悟空》免安装学习版【全dlc整合完整版】+Steam游戏解锁+游戏修改工具!
[动画] 《名侦探柯南》名侦探柯南百万美元的五菱星 [TC] [MP4]
[动画] 2002《火影忍者》720集全【4K典藏版】+11部剧场版+OVA+漫画 内嵌简日字幕
[剧集] 《斯巴达克斯》1-4季合集 无删减版 1080P 内嵌简英特效字幕
[CG剧情] 《黑神话:悟空》158分钟CG完整剧情合集 4K120帧最高画质
[电影] 《变形金刚系列》七部合集 [4K HDR 蓝光] 国英双语音轨 [内封精品特效字幕]【典藏版】235G
[游戏] 黑神话悟空离线完整版+修改器
[动画] 收藏版:1996-2024年名侦探柯南全系列1080P,含国配、日配双语版+26部剧场作品
[动画] 西游记 (1999) 动画版 4K 全52集 高清修复版 童年回忆
[影视] 美国内战 4K蓝光原盘下载+高清MKV版/内战/帝国浩劫:美国内战(台)/美帝崩裂(港) 2024 Civil War 63.86G
[影视] 一命 3D 蓝光高清MKV版/切腹 / 切腹:武士之死 / Hara-Kiri: Death of a Samurai / Ichimei 2011 一命 13.6G
[影视] 爱情我你他 蓝光原盘下载+高清MKV版/你、我、他她他 2005 Me and You and Everyone We Know 23.2G
[影视] 穿越美国 蓝光原盘下载+高清MKV版/窈窕老爸 / 寻找他妈…的故事 2005 Transamerica 20.8G
[电影] 《黄飞鸿》全系列合集
[Android] 开罗游戏 ▎像素风格的模拟经营的游戏厂商安卓游戏大合集
[游戏合集] 要战便战 v0.9.107 免安装绿色中文版
[电影] 【珍藏版】20世纪电影合集从1922年到1990年代,看看爷爷辈的电影是什么样合集约212G
[书籍] 彭子益医书合集 [PDF/DOC]
[系统]【黑果小兵】macOS Big Sur 11.0.1 20B50 正式版 with Clover 5126 黑苹果系统镜像下载
- 最新评论
-
一部不错的经典科幻kelvin 评论于:11-13 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢285552528 评论于:11-09 找了好久的资源bjzchzch12 评论于:11-07 谢谢分享感谢ppy2016 评论于:11-05 谢谢分享感谢ppy2016 评论于:11-05 有靳东!嘻嘻奥古斯都.凯撒 评论于:10-28 流星花园是F4处女作也是4人集体搭配的唯一一部!奥古斯都.凯撒 评论于:10-28 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢AAAAA 评论于:10-26 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢password63 评论于:10-26 找了好久的资源,终于在这里找齐了!!!!blog001 评论于:10-21
- 热门tag