最近两天的leetcode刷题记录。
文章目录
- 6.17
- [1014. 最佳观光组合](https://leetcode-cn.com/problems/best-sightseeing-pair/)
- [532. 数组中的K-diff数对](https://leetcode-cn.com/problems/k-diff-pairs-in-an-array/)
- [530. 二叉搜索树的最小绝对差](https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst/)
- [404. 左叶子之和](https://leetcode-cn.com/problems/sum-of-left-leaves/)
- [104. 二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
- [111. 二叉树的最小深度](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/)
- [102. 二叉树的层序遍历](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
- [107. 二叉树的层次遍历 II](https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/)
- [637. 二叉树的层平均值](https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/)
- [606. 根据二叉树创建字符串](https://leetcode-cn.com/problems/construct-string-from-binary-tree/)
- [35. 搜索插入位置](https://leetcode-cn.com/problems/search-insert-position/)
- [278. 第一个错误的版本](https://leetcode-cn.com/problems/first-bad-version/)
- [34. 在排序数组中查找元素的第一个和最后一个位置](https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/)
- [695. 岛屿的最大面积](https://leetcode-cn.com/problems/max-area-of-island/)
- 6.18
- [1028. 从先序遍历还原二叉树](https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal/)
- [116. 填充每个节点的下一个右侧节点指针](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/)
- [117. 填充每个节点的下一个右侧节点指针 II](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/)
- [1110. 删点成林](https://leetcode-cn.com/problems/delete-nodes-and-return-forest/)
- [13. 罗马数字转整数](https://leetcode-cn.com/problems/roman-to-integer/)
- [12. 整数转罗马数字](https://leetcode-cn.com/problems/integer-to-roman/)
- [6. Z 字形变换](https://leetcode-cn.com/problems/zigzag-conversion/)
- [151. 翻转字符串里的单词](https://leetcode-cn.com/problems/reverse-words-in-a-string/)
- [21. 合并两个有序链表](https://leetcode-cn.com/problems/merge-two-sorted-lists/)
- [148. 排序链表](https://leetcode-cn.com/problems/sort-list/)
- [147. 对链表进行插入排序](https://leetcode-cn.com/problems/insertion-sort-list/)
- [面试题42. 连续子数组的最大和](https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/)
- [392. 判断子序列](https://leetcode-cn.com/problems/is-subsequence/)
- [88. 合并两个有序数组](https://leetcode-cn.com/problems/merge-sorted-array/)
- [977. 有序数组的平方](https://leetcode-cn.com/problems/squares-of-a-sorted-array/)
6.17
1014. 最佳观光组合
难度中等
快速的写了一个双重循环,果然超出时间限制。之后观察它的得分方程,发现可以拆分成A[i] + i和A[j] - j两部分。而A[j]-j是一个固定的值,所以最后的结果就是寻找A[i] + i的最大值。这样的话就能在一次遍历就解决问题。
class Solution {
public int maxScoreSightseeingPair(int[] A) {
int ans = 0;
int mx = 0;
for(int i = 0;i < A.length;i++){
ans = Math.max(mx + A[i] - i, ans);
mx = Math.max(mx, A[i] + i);
}
return ans;
}
}
532. 数组中的K-diff数对
难度简单
最终还是用暴力法解决的。
class Solution {
public int findPairs(int[] nums, int k) {
if(nums == null || nums.length == 0){
return 0;
}
int ans = 0;
Arrays.sort(nums);
int num = nums[0];
for(int i = 0;i < nums.length;i++){
if(num == nums[i] && i != 0){
continue;
}
for(int j = i + 1;j < nums.length;j++){
if(Math.abs(nums[j] - nums[i]) == k){
ans++;
break;
}
}
num = nums[i];
}
return ans;
}
}
530. 二叉搜索树的最小绝对差
难度简单
因为是二叉搜索树,所以可以先用中序遍历得到从小到大的排列,之后将链表转成数组,对数组操作得到最小绝对差就可以了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int getMinimumDifference(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
midOrder(root, list);
Integer[] arr = new Integer[list.size()];
int minDiff = Integer.MAX_VALUE;
list.toArray(arr);
if(arr.length == 2){
return arr[1] - arr[0];
}
for(int i = 1;i < arr.length;i++){
minDiff = Math.min(arr[i] - arr[i - 1], minDiff);
}
return minDiff;
}
public void midOrder(TreeNode root, ArrayList<Integer> list){
if(root == null){
return ;
}
midOrder(root.left, list);
list.add(root.val);
midOrder(root.right, list);
}
}
404. 左叶子之和
难度简单
计算出左右子树的所有左叶子的和即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null){
return 0;
}
int sumL = getLeftLeaves(root.left, true);
int sumR = getLeftLeaves(root.right, false);
return sumR + sumL;
}
public int getLeftLeaves(TreeNode root, boolean isLeft){
if(root == null){
return 0;
}
if(root.left == null && root.right == null && isLeft){
return root.val;
}
int sumL = getLeftLeaves(root.left, true);
int sumR = getLeftLeaves(root.right, false);
return sumL + sumR;
}
}
104. 二叉树的最大深度
难度简单
这个题应该算是比较经典的题目了。用递归即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
}
111. 二叉树的最小深度
难度简单
这个题和前一个题类似,只不过需要注意的是左右子树为空时的情况,需要对其进行特殊处理。因为题目所要求的是指根节点到叶节点的最短路径长度。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
int left = minDepth(root.left);
int right = minDepth(root.right);
if(left == 0){//没有左子树
return right + 1;
}
if(right == 0){//没有右子树
return left + 1;
}
return Math.min(left, right) + 1;
}
}
102. 二叉树的层序遍历
难度中等
这个题也算是比较经典的题目了。之前在《剑指》上也做过,现在能直接秒了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new LinkedList<>();
if(root == null){
return result;
}
int curr = 1;
int next = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> list = new LinkedList<>();
while(curr > 0){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null){
queue.offer(node.left);
next++;
}
if(node.right != null){
queue.offer(node.right);
next++;
}
curr--;
}
result.add(list);
curr = next;
next = 0;
}
return result;
}
}
107. 二叉树的层次遍历 II
难度简单
这个题就是上个题的变种,只需要利用栈的先进后出的特性就能实现了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> result = new LinkedList<>();
Stack<List<Integer>> stack = new Stack<>();
if(root == null){
return result;
}
int curr = 1;
int next = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> list = new LinkedList<>();
while(curr > 0){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null){
queue.offer(node.left);
next++;
}
if(node.right != null){
queue.offer(node.right);
next++;
}
curr--;
}
stack.push(list);
curr = next;
next = 0;
}
while(!stack.isEmpty()){
result.add(stack.pop());
}
return result;
}
}
637. 二叉树的层平均值
难度简单
这类二叉树的层次问题其实都是一种类型的题目,用bfs算法就能轻松解决。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> result = new LinkedList<>();
if(root == null){
return result;
}
int curr = 1;
int next = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
double sum = 0;
int temp = curr;
while(curr > 0){
TreeNode node = queue.poll();
sum += node.val;
if(node.left != null){
queue.offer(node.left);
next++;
}
if(node.right != null){
queue.offer(node.right);
next++;
}
curr--;
}
result.add((double) sum / temp);
curr = next;
next = 0;
}
return result;
}
}
606. 根据二叉树创建字符串
难度简单
一个变相的dfs算法。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public String tree2str(TreeNode t) {
if(t == null){
return "";
}
String str = String.valueOf(t.val);
if(t.left == null && t.right == null){
return str;
}
//左右子树要分开处理
if(t.left == null){
str += "()";
}else{
str += "(" + tree2str(t.left) + ")";
}
if(t.right != null){
str += "(" + tree2str(t.right) + ")";
}
return str;
}
}
35. 搜索插入位置
难度简单
emmm,很简单一个题,没什么好说的。
class Solution {
public int searchInsert(int[] nums, int target) {
int i = 0;
for(; i < nums.length;i++){
if(nums[i] >= target){
break;
}
}
return i;
}
}
278. 第一个错误的版本
难度简单
因为要可能减少调用API的次数,所以就采用二分查找的方法来实现。其中需要注意的是在算mid时,,如果使用(left+right)/ 2可能会导致溢出问题,所以应该采用相减再相加的方式。而且n是从1开始的。
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int begin = 1;
int end = n;
int mid;
while(begin < end){
mid = begin + (end - begin) / 2;
if(isBadVersion(mid)){
end = mid;
}else{
begin = mid + 1;
}
}
return begin;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
难度中等
利用二分查找先找到目标元素。找到二分元素之后再对其前后进行遍历,找到第一个和最后一个位置。
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
int begin = 0;
int end = nums.length - 1;
int mid;
while(begin <= end){
mid = begin + (end - begin) / 2;
if(nums[mid] == target){
int index = mid - 1;
System.out.println();
while(index >= 0 && nums[index] == target){
index--;
}
result[0] = index + 1;
index = mid + 1;
while(index < nums.length && nums[index] == target){
index++;
}
result[1] = index - 1;
break;
}else if(nums[mid] > target){
end = mid - 1;
}else{
begin = mid + 1;
}
}
return result;
}
}
695. 岛屿的最大面积
难度中等
用dfs实现可以了。
class Solution {
public int maxAreaOfIsland(int[][] grid) {
boolean[][] isVisited = new boolean[grid.length][grid[0].length];
int max = 0;
for(int i = 0;i < grid.length;i++){
for(int j = 0;j < grid[0].length;j++){
if(grid[i][j] == 1 && !isVisited[i][j]){
int num = dfs(grid, isVisited, i, j);
max = Math.max(num, max);
}
}
}
return max;
}
public int dfs(int[][] grid, boolean[][] isVisited, int i, int j){
int num = 0;
if(i >= 0 && i < grid.length && j >= 0 && j < grid[0].length &&
grid[i][j] == 1 && !isVisited[i][j]){
isVisited[i][j] = true;
num = dfs(grid, isVisited, i + 1, j) +
dfs(grid, isVisited, i - 1, j) +
dfs(grid, isVisited, i, j - 1) +
dfs(grid, isVisited, i, j + 1) + 1;
}
return num;
}
}
6.18
1028. 从先序遍历还原二叉树
难度困难
做了一个多小时终于做出来了。只不过是按照逻辑硬解出来的。其中考虑各种边界情况,真的很烦。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode recoverFromPreorder(String S) {
if(S == null || S.length() == 0){
return null;
}
return recoverFromPreorder(S, "-");
}
public TreeNode recoverFromPreorder(String str, String splice){
TreeNode root = null;
int count = 0;
int indexL = 0;
int indexR = 0;
int isRootOrLeftOrRight = 0;//0代表root,1代表left,2代表right
for(int i = 0;i < str.length();i++){
if(str.charAt(i) == '-'){
count++;
}else{
count = 0;
}
if(count == splice.length() && i < str.length() - 1 && str.charAt(i + 1) != '-'){
switch(isRootOrLeftOrRight){
case 0:
indexL = i + 1;
String rootValue = str.substring(0, str.indexOf(splice));
root = new TreeNode(Integer.parseInt(rootValue));
break;
case 1:
indexR = i + 1;
root.left = recoverFromPreorder(
str.substring(indexL, indexR - splice.length()), splice + "-"
);
break;
default:
break;
}
count = 0;
isRootOrLeftOrRight++;
}
}
if(indexL == 0){
return new TreeNode(Integer.parseInt(str));
}
if(indexR != 0){
root.right = recoverFromPreorder(str.substring(indexR), splice + "-");
}
if(isRootOrLeftOrRight == 1){
int end = indexR - splice.length();
if(indexR != 0){
root.left = recoverFromPreorder(
str.substring(indexL, end), splice + "-"
);
}else{
root.left = recoverFromPreorder(
str.substring(indexL), splice + "-"
);
}
}
return root;
}
}
116. 填充每个节点的下一个右侧节点指针
难度中等
感觉在哪见过这个题,但就是做不出来,很绝望。看了题解之后开始有点理解。
class Solution {
public Node connect(Node root) {
if (root == null) {
return root;
}
Node leftmost = root;
while (leftmost.left != null) {
Node head = leftmost;
while (head != null) {//层次遍历
//子节点的左右相连
head.left.next = head.right;
//分隔节点的左右相连
if (head.next != null) {
head.right.next = head.next.left;
}
head = head.next;
}
//进入下一层
leftmost = leftmost.left;
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 II
难度中等
在前一题的基础上去除了完美二叉树的条件,说明可能右多种形式的二叉树。
我自己做了好久没有解决,最后还是参照题解才做出来。继续加油。
class Solution {
public Node connect(Node root) {
if(root==null){
return null;
}
if(root.left==null && root.right==null){
return root;
}
if(root.left!=null&&root.right!=null){
root.left.next=root.right;
root.right.next=getNextNode(root);
}
if(root.left==null){
root.right.next=getNextNode(root);
}
if(root.right==null){
root.left.next=getNextNode(root);
}
connect(root.right);
connect(root.left);
return root;
}
public Node getNextNode(Node node){
while(node.next!=null){
if(node.next.left!=null){
return node.next.left;
}
if(node.next.right!=null){
return node.next.right;
}
node=node.next;
}
return null;
}
}
1110. 删点成林
难度中等
这个题春招面试的时候没做出来,事后一看题解发现也不是特别难,当时还特别可惜。现在可以成功做出来,也算是有点进步了吧。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
Set<Integer> set = new HashSet<>();
for(int num : to_delete){
set.add(num);
}
List<TreeNode> ans = new LinkedList<>();
dfs(root, set, ans, true);
return ans;
}
public boolean dfs(TreeNode root, Set<Integer> set, List<TreeNode> ans, boolean isRoot){
if(root == null){
return false;
}
if(!set.contains(root.val)){//如果不包含
if(isRoot){//如果是根节点
ans.add(root);
}
if(dfs(root.left, set, ans, false)){
root.left = null;
}
if(dfs(root.right, set, ans, false)){
root.right = null;
}
}else{
if(dfs(root.left, set, ans, true)){
root.left = null;
}
if(dfs(root.right, set, ans, true)){
root.right = null;
}
return true;
}
return false;
}
}
13. 罗马数字转整数
难度简单
简单的字符串遍历
class Solution {
public int romanToInt(String s) {
int num = 0;
for(int i = 0;i < s.length();i++){
switch(s.charAt(i)){
case 'I':
if(i < s.length() - 1){
if(s.charAt(i + 1) == 'V'){
num += 4;
i++;
continue;
}else if(s.charAt(i + 1) == 'X'){
num += 9;
i++;
continue;
}
}
num += 1;
break;
case 'X':
if(i < s.length() - 1){
if(s.charAt(i + 1) == 'L'){
num += 40;
i++;
continue;
}else if(s.charAt(i + 1) == 'C'){
num += 90;
i++;
continue;
}
}
num += 10;
break;
case 'C':
if(i < s.length() - 1){
if(s.charAt(i + 1) == 'D'){
num += 400;
i++;
continue;
}else if(s.charAt(i + 1) == 'M'){
num += 900;
i++;
continue;
}
}
num += 100;
break;
case 'L':
num += 50;
break;
case 'V':
num += 5;
break;
case 'D':
num += 500;
break;
case 'M':
num += 1000;
break;
default:
break;
}
}
return num;
}
}
12. 整数转罗马数字
难度中等
上一个题的反转,根据所有的罗马数字所能代表的值,从大到小寻找就行了。
class Solution {
String str = "";
public String intToRoman(int num) {
num = intToRoman(num, 1000, "M");
num = intToRoman(num, 900, "CM");
num = intToRoman(num, 500, "D");
num = intToRoman(num, 400, "CD");
num = intToRoman(num, 100, "C");
num = intToRoman(num, 90, "XC");
num = intToRoman(num, 50, "L");
num = intToRoman(num, 40, "XL");
num = intToRoman(num, 10, "X");
num = intToRoman(num, 9, "IX");
num = intToRoman(num, 5, "V");
num = intToRoman(num, 4, "IV");
num = intToRoman(num, 1, "I");
return str;
}
public int intToRoman(int num, int m, String roman){
int temp = num / m;
while(temp != 0){
str += roman;
temp--;
num -= m;
}
return num;
}
}
6. Z 字形变换
难度中等
最开始想要用二维数组来做,但是觉得太麻烦了,应该不是用这样的做法解决的问题。后来去参照题解想通了。
class Solution {
public String convert(String s, int numRows) {
if(numRows == 1){
return s;
}
List<StringBuilder> list = new ArrayList<>();
for(int i = 0;i < numRows;i++){
list.add(new StringBuilder());
}
int curRow = 0;
boolean goDown = false;//初始化为false,因为之后会反转
for(char c : s.toCharArray()){
list.get(curRow).append(String.valueOf(c));
if(curRow == 0 || curRow == numRows - 1){
goDown = !goDown;
}
curRow += goDown ? 1 : -1;
}
String ans = "";
for(StringBuilder str : list){
ans += str.toString();
}
return ans;
}
}
151. 翻转字符串里的单词
难度中等
这个题也算是比较简单的题目了吧。利用String的几个方法就行了。
class Solution {
public String reverseWords(String s) {
String[] arr = s.trim().split(" ");
StringBuilder ans = new StringBuilder();
for(int i = arr.length - 1;i >= 0;i--){
if(arr[i].equals("")){
continue;
}
ans.append(arr[i]).append(" ");
}
return ans.toString().trim();
}
}
21. 合并两个有序链表
难度简单
利用一个哨兵节点和递归就能做出来。
/**
* Definition for singly-linked list.
* public 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 Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
ListNode head = new ListNode();
if(l1.val <= l2.val){
head.next = l1;
head.next.next = mergeTwoLists(l1.next, l2);
}else{
head.next = l2;
head.next.next = mergeTwoLists(l2.next, l1);
}
return head.next;
}
}
148. 排序链表
难度中等
题目要求是在 O(n log n) 时间复杂度和常数级空间复杂度下,不然我想用单调栈来解决。既然是nlogn的时间复杂度,那么就应该用二分的思想来实现。排序的话就是归并排序。我们把中间节点找出来,把链表断开,左右链表分别排序,最后又合并在一起就可以了。(参照了题解)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head == null){
return null;
}
if(head.next == null){
return head;
}
ListNode fast = head;
ListNode slow = head;
ListNode pre = null;
while(fast != null && fast.next != null){
fast = fast.next.next;
pre = slow;
slow = slow.next;
}
pre.next = null;
ListNode left = sortList(head);
ListNode right = sortList(slow);
return merge(left, right);
}
public ListNode merge(ListNode left, ListNode right){
ListNode pre = new ListNode(0);
ListNode cur = pre;
// 比较左右链表
while (left != null && right != null) {
if (left.val <= right.val) {
cur.next = left;
cur = cur.next;
left = left.next;
} else {
cur.next = right;
cur = cur.next;
right = right.next;
}
}
if (left != null) {
cur.next = left;
}
if (right != null) {
cur.next = right;
}
return pre.next;
}
}
147. 对链表进行插入排序
难度中等
自己写了一种解法。不过频繁的交换值导致效率不高。希望还能有优化。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head == null){
return null;
}
int len = 0;
ListNode node = head;
while(node != null){
node = node.next;
len++;
}
for(int i = 0;i < len;i++){
node = head;
int index = 0;
while(index < i){
node = node.next;
index++;
}
int m = 0;
ListNode temp = head;
while(m < i){
if(temp.val > node.val){
int ss = temp.val;
temp.val = node.val;
node.val = ss;
}
temp = temp.next;
m++;
}
}
return head;
}
}
参照了题解,做了一点优化。思路就是不换值,而是更新节点的next索引。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode dummy = new ListNode();
ListNode pre = head;
ListNode cur = head.next;
dummy.next = head;
while(cur != null){
if(cur.val >= pre.val){//原本就有序
pre = cur;
cur = cur.next;
}else{
ListNode temp = dummy;
while(temp.next != cur && temp.next.val < cur.val){//找到最后一个小于该节点的节点
temp = temp.next;
}
//将之前的排序链表与之后的链表相连
pre.next = cur.next;
//更新当前节点的next节点
cur.next = temp.next;
//更新最后一个小于当前节点的节点的next索引
temp.next = cur;
//更新当前节点
cur = pre.next;
}
}
return dummy.next;
}
}
面试题42. 连续子数组的最大和
难度简单
也是比较经典的题目了,之前在《剑指》中做过。现在直接秒了。
class Solution {
public int maxSubArray(int[] nums) {
int sum = 0;
int maxSum = Integer.MIN_VALUE;
for(int num : nums){
if(sum < 0){
sum = num;
}else{
sum += num;
}
maxSum = Math.max(sum, maxSum);
}
return maxSum;
}
}
392. 判断子序列
难度简单
出现了第一个自己做出双百的题目。虽然它的标签是二分、贪婪和动态规划,但是不知道为什么我这样的做法竟然是双百的解法,好神奇。
思路就是利用String的indexOf方法来对s的每一个字符来进行匹配。当找不到时就可以说两个字符串不满足条件。
class Solution {
public boolean isSubsequence(String s, String t) {
if(s.length() > t.length()){
return false;
}
int index = -1;
for(int i = 0;i < s.length();i++){
int temp = t.indexOf(String.valueOf(s.charAt(i)), index + 1);
if(temp == -1 || temp < index){
return false;
}else{
index = temp;
}
}
return true;
}
}
88. 合并两个有序数组
难度简单
从数组的后面,也就是从大的开始排序。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int length = m + n;
m--;
n--;
for(int i = length - 1;i >= 0;i--){
if(m >= 0 && n >= 0){
if(nums1[m] < nums2[n]){
nums1[i] = nums2[n--];
}else{
nums1[i] = nums1[m--];
}
}else if(m >= 0){
nums1[i] = nums1[m--];
}else{
nums1[i] = nums2[n--];
}
}
}
}
977. 有序数组的平方
难度简单
双指针,先找到正负数分隔的地方,之后再比较两个指针的绝对值决定添加哪一个就行了。
class Solution {
public int[] sortedSquares(int[] A) {
if(A.length == 1){
return new int[] {A[0] * A[0]};
}
int L = 0;
int R = 0;
for(int i = 0;i < A.length;i++){
if(A[i] >= 0){
R = i;
L = i - 1;
break;
}
}
int[] ans = new int[A.length];
int index = 0;
while(L >= 0 || R < A.length){
if(L >= 0 && R < A.length){
if(Math.abs(A[L]) < A[R]){
ans[index] = A[L] * A[L];
L--;
}else{
ans[index] = A[R] * A[R];
R++;
}
}else if(L >= 0){
ans[index] = A[L] * A[L];
L--;
}else{
ans[index] = A[R] * A[R];
R++;
}
index++;
}
return ans;
}
}