因为最近两天在准备考试,所以几乎没怎么做。明天继续做题,加油加油!
文章目录
- 6.21
- [124. 二叉树中的最大路径和](https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/)
- [687. 最长同值路径](https://leetcode-cn.com/problems/longest-univalue-path/)
- [19. 删除链表的倒数第N个节点](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)
- [4. 寻找两个正序数组的中位数](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/)
- [11. 盛最多水的容器](https://leetcode-cn.com/problems/container-with-most-water/)
- 6.22
- 6.23
6.21
124. 二叉树中的最大路径和
难度困难
难点就是这个路径能从任意节点出发,并且能在任意节点结束。当到达一个节点时,就要考虑左右子树的收益够不够大,只加上收益大于0的就行了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int maxSum = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxGain(root);
return maxSum;
}
public int maxGain(TreeNode root){
if(root == null){
return 0;
}
int left = Math.max(maxGain(root.left), 0);
int right = Math.max(maxGain(root.right), 0);
int sum = root.val + left + right;
maxSum = Math.max(maxSum, sum);
return root.val + Math.max(left, right);
}
}
687. 最长同值路径
难度简单
这个题难点就在于开始节点和结束节点都没有限制。参照了答案之后做了出来。不过我遇到一个问题,为什么我这样写就无法通过。因为我觉得这两种写法应该是同一个效果。
public int dfs(TreeNode root){
if(root == null){
return 0;
}
int leftLen = dfs(root.left);
int rightLen = dfs(root.right);
if(root.left != null && root.left.val == root.val){
leftLen ++;
}
if(root.right != null && root.right.val == root.val){
rightLen ++;
}
maxNum = Math.max(maxNum, leftLen + rightLen);
return Math.max(leftLen, rightLen);
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int maxNum = 0;
public int longestUnivaluePath(TreeNode root) {
dfs(root);
return maxNum;
}
public int dfs(TreeNode root){
if(root == null){
return 0;
}
int leftLen = dfs(root.left);
int rightLen = dfs(root.right);
int arrowLeft = 0;
int arrowRight = 0;
if(root.left != null && root.left.val == root.val){
arrowLeft = leftLen + 1;
}
if(root.right != null && root.right.val == root.val){
arrowRight = rightLen + 1;
}
maxNum = Math.max(maxNum, arrowLeft + arrowRight);
return Math.max(arrowLeft, arrowRight);
}
}
19. 删除链表的倒数第N个节点
难度中等
删除的节点可能是头结点,也可能是尾节点,也有可能是正常的中间节点。
如果删除节点是头结点,就判断最后的slow节点是否与之前的头结点相同,如果相同,则说明要删除的是头结点,更新头结点。
如果删除节点是尾节点,我们需要一个节点来记录下之前遍历到的最后一个节点,把它的next更新为null。
如果删除节点是中间节点,就需要更换下一节点的值,并更新其next就行。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null){
return null;
}
int k = 0;
ListNode fast = head;
ListNode slow = head;
while(k < n){
if(fast == null){//n比链表长度长
return null;
}
fast = fast.next;
k++;
}
ListNode pre = null;
while(fast != null){
pre = slow;
slow = slow.next;
fast = fast.next;
}
System.out.println(slow.val);
if(slow == head){//头结点
head = slow.next;
}else{
if(slow.next == null){//删除的是尾节点
pre.next = null;
}else{//删除的是中间节点
slow.val = slow.next.val;
slow.next = slow.next.next;
}
}
return head;
}
}
4. 寻找两个正序数组的中位数
难度困难
开心,又是一道双百的题,而且难度还是困难。
借助了一个数组来存储已经排序过的数据。因为只用找到中位数,所以我们只用排序到中间的位置。之后再判断数组长度的奇偶决定返回的中位数就行了。
不过这样的解法并没有达到题目的要求log(m + n)
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int length = nums1.length + nums2.length;
int[] mergeNums = new int[length];
int index1 = 0;
int index2 = 0;
int mid = length / 2;
int index = 0;
while(index <= mid){
int num1 = index1 < nums1.length ? nums1[index1] : Integer.MAX_VALUE;
int num2 = index2 < nums2.length ? nums2[index2] : Integer.MAX_VALUE;
if(num1 < num2){
mergeNums[index] = nums1[index1];
index1++;
}else{
mergeNums[index] = nums2[index2];
index2++;
}
index++;
}
if(length % 2 == 0){
return (double)(mergeNums[mid] + mergeNums[mid - 1]) / 2;
}else{
return (double)mergeNums[mid];
}
}
}
11. 盛最多水的容器
难度中等
首先用暴力法解决。
class Solution {
public int maxArea(int[] height) {
int max = -1;
for(int i = 0;i < height.length;i++){
for(int j = height.length - 1;j > i;j--){
max = Math.max(max, (j - i) * Math.min(height[i], height[j]));
}
}
return max <= 0 ? 0 : max;
}
}
看了题解之后发现可以用双指针的方式来做。
思想就是假设l是左边界,r是右边界。当左边界的值小于右边界时,存在更多水量的可能只会在左边界右移的情况。(每次都尝试固定左右边界中较高的值,改变低的值)
class Solution {
public int maxArea(int[] height) {
int l = 0;
int r = height.length - 1;
int ans = 0;
while(l < r){
int sum = Math.min(height[l], height[r]) * (r - l);
ans = Math.max(ans, sum);
if(height[l] <= height[r]){
l++;
}else{
r--;
}
}
return ans <= 0 ? 0 : ans;
}
}
6.22
441. 排列硬币
难度简单
简单的一个数学问题。
class Solution {
public int arrangeCoins(int n) {
if(n < 1){
return 0;
}
int row = 0;
while(n > 0){
row++;
n -= row;
}
if(n < 0){
return row - 1;
}else{
return row;
}
}
}
看了题解发现还能用二分查找来解决问题。其中需要注意的是n可能会越界,导致错误的情况。所以我在计算及比较时利用了long,等到最后返回时再强制转换成int。
class Solution {
public int arrangeCoins(int n) {
if(n < 1){
return 0;
}
long left = 0;
long right = n;
while(left <= right){
long mid = left + (right - left) / 2;
long sum = (mid + 1) * mid / 2;//等差数列求和
if(sum == (long)n){
return (int)mid;
}else if(sum < (long)n){
left = mid + 1;
}else if(sum > (long)n){
right = mid - 1;
}
}
return (int)right;
}
}
6.23
67. 二进制求和
难度简单
感觉我把他做成了普遍的字符串相加,如果再加参数的话可以实现不同进制的转换。
class Solution {
public String addBinary(String a, String b) {
char[] arr1 = a.toCharArray();
char[] arr2 = b.toCharArray();
Stack<Integer> stack = new Stack<>();
int index1 = arr1.length - 1;
int index2 = arr2.length - 1;
int carry = 0;
while(index1 >= 0 || index2 >= 0){
int num1 = index1 >= 0 ?Integer.parseInt(String.valueOf(arr1[index1])) : 0;
int num2 = index2 >= 0 ?Integer.parseInt(String.valueOf(arr2[index2])) : 0;
int sum = num1 + num2 + carry;
carry = sum / 2;
int num = sum % 2;
stack.push(num);
index1--;
index2--;
}
if(carry > 0){
stack.push(carry);
}
String ans = "";
while(!stack.isEmpty()){
ans += String.valueOf(stack.pop());
}
return ans;
}
}