leetcode 随笔10

因为最近两天在准备考试,所以几乎没怎么做。明天继续做题,加油加油!

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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值