力扣爆刷第151天之TOP100五连刷(回文子串、DFS、旋转数组二分查找)
文章目录
- 力扣爆刷第151天之TOP100五连刷(回文子串、DFS、旋转数组二分查找)
- 一、5. 最长回文子串
- 二、102. 二叉树的层序遍历
- 三、33. 搜索旋转排序数组
- 四、200. 岛屿数量
- 五、20. 有效的括号
一、5. 最长回文子串
题目链接:https://leetcode.cn/problems/longest-palindromic-substring/description/
思路:求最长回文子串,最简单的思路就是遍历寻找,当然遍历寻找也是需要技巧,从任意一个点位开始,向左右进行对比是否想对。中心的点位可以是1个也可以是2个。如aba,abba,这种。所以分两种情况进行遍历。
class Solution {public String longestPalindrome(String s) {String max = "";for(int i = 0; i < s.length(); i++) {String left = findStr(s, i, i);String right = findStr(s, i, i+1);if(max.length() < left.length()) max = left;if(max.length() < right.length()) max = right;}return max;}String findStr(String s, int left, int right) {while(left >= 0 && right < s.length()) {if(s.charAt(left) != s.charAt(right)) break;left--;right++;}return s.substring(left+1, right);}
}
二、102. 二叉树的层序遍历
题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/description/
思路:很经典的题目,只需要借助队列即可实现,先把根节点入队,这样就有了第一层的所有节点,可以获取每一层的节点数量,通过这个节点数量劲出队操作,然后再把子节点加入进来。由此即可实现层序遍历,其中关键点就是每一层的节点数量,这个是由根节点启动的。
class Solution {List<List<Integer>> result = new ArrayList<>();public List<List<Integer>> levelOrder(TreeNode root) {if(root == null) return result;LinkedList<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()) {int size = queue.size();List<Integer> list = new ArrayList<>();for(int i = 0; i < size; i++) {TreeNode node = queue.poll();list.add(node.val);if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);}result.add(list);}return result;}
}
三、33. 搜索旋转排序数组
题目链接:https://leetcode.cn/problems/search-in-rotated-sorted-array/description/
思路:题目的意思是把数组从中间任意一个位置截取然后左右互换来形成旋转,其实只要是细心一些就会发现,无论这种选择操作进行多少次,最后都是一个形状,也就是如下的形状,题目要求时间复杂度log(n),显然二分查找,非递增怎么进行二分查找呢?其实很简单,一样是计算中值,只不过之前是计算中值之后和target进行比较,来判断target位于哪一个区间,现在依然要进行这一步,却需要先用中值与左边界进行比较,可以得到点位①和点位②是情况。
如果是点位①,则可以通过targer与点位①和左边界的比较来判断,该去点位①的左边寻找target还是右边。
如果是点位②,同样如此。
class Solution {public int search(int[] nums, int target) {int left = 0, right = nums.length-1;while(left <= right) {int mid = left + (right - left) / 2;if(nums[mid] == target) return mid;if(nums[mid] >= nums[left]) {if(target >= nums[left] && target < nums[mid]) right = mid - 1;else left = mid + 1;}else{if(target > nums[mid] && target <= nums[right]) left = mid + 1;else right = mid - 1;}}return -1;}
}
四、200. 岛屿数量
题目链接:https://leetcode.cn/problems/number-of-islands/description/
思路:经典深度优先求岛屿数量,进入岛屿就进行DFS,然后把遍历过岛屿都改成海洋即可。
class Solution {public int numIslands(char[][] grid) {int count = 0;for(int i = 0; i < grid.length; i++) {for(int j = 0; j < grid[0].length; j++) {if(grid[i][j] == '1') {dfs(grid, i, j);count++;}}}return count;}void dfs(char[][] grid, int x, int y) {if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] == '0') return;grid[x][y] = '0';dfs(grid, x-1, y);dfs(grid, x+1, y);dfs(grid, x, y-1);dfs(grid, x, y+1);}
}
五、20. 有效的括号
题目链接:https://leetcode.cn/problems/valid-parentheses/description/
思路:经典题目了,有三种类型的括号,然后求是否是有效括号,其实只需要如果遇到左括号就把右括号入栈即可,如果遇到右括号就与栈顶进行比较,不等即错。
class Solution {public boolean isValid(String s) {LinkedList<Character> stack = new LinkedList<>();for(int i = 0; i < s.length(); i++) {char c = s.charAt(i);if(c == '(') stack.push(')');else if(c == '[') stack.push(']');else if(c == '{') stack.push('}');else if(!stack.isEmpty() && c == stack.peek()) stack.poll();else return false;}return stack.isEmpty();}
}