leetcode简单题解(二)


一、链表的中间结点

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/middle-of-the-linked-list

描述:

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:35.8 MB, 在所有 Java 提交中击败了45.60%的用户

第一种:
class Solution {
    public ListNode middleNode(ListNode head) {
        int n=0;
        ListNode head1=head;
        for(;head!=null;n++){
            head=head.next;
        }
        for(int i=0;i<n/2;i++){
            head1=head1.next;
        }
        return head1;
    }
}
这个是我的第一反应,以空间换时间的解法,整体遍历一遍链表的个数,再遍历输出中值

第二种:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:35.5 MB, 在所有 Java 提交中击败了96.00%的用户
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode a=head;
        ListNode b=head;
        while(b!=null && b.next!=null){
           b=b.next.next;
           a=a.next;
        }
        return a;
    }
}
做完之后看题解发现居然没想到这种解法,这个很巧妙,快慢指针,慢指针走快指针的一半,那么快指针走完时慢指针正好就是中值。

二、删除链表的倒数第 N 个结点(中等题)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/middle-of-the-linked-list

描述:

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

示例:

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.2 MB,在所有 Java 提交中击败了85.46%的用户

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode head0=new ListNode(0,head);
        ListNode a=head0,b=head;
        while(n-->0){
             b=b.next;
        }
        for(;b!=null;){
            b=b.next;
            a=a.next;
        }
        a.next=a.next.next;
        return head0.next;
    }
}
中等题,题的思路很简单,快慢指针,快的比慢的早走n步,就能打出来一个n的差值。
一开始没有做出来,虽然有思路,但是被删除头结点等奇怪的边界问题难住了,陷入了固定思维,看了题解才猛然发现可以在头结点前再设一个结点来解决.......
其实做不出来本质上还是实践不够多、理解不够深。

三、删除排序数组中的重复项 II(中等题)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii

描述:

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。

示例2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.4 MB, 在所有 Java 提交中击败了83.82%的用户

class Solution {
    public int removeDuplicates(int[] nums) {
        int j=1;
        for(int i=1,num=1;i<nums.length;i++){
            if(nums[i]!=nums[i-1]){
                num=1;
                nums[j++]=nums[i];
                continue;
            }else{
                num++;
            }
            if(num<3){
                 nums[j++]=nums[i];
            }
        }
        return j;
    }
}
这个虽然标的是中等题,但难度却像个简单题,思路很简单,既然让原地修改,那么自然而然地想到用快慢指针,同时设置一个计数的num,然后只需要给慢指针,即j赋值就行了。

四、盛最多水的容器(中等题)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water

描述:

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

在这里插入图片描述
示例1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例2:

输入:height = [1,1]
输出:1

解决:


class Solution {
    public int maxArea(int[] height) {
       int max=0;
       for(int i=0,j=height.length-1;i<j;){
           max=max<(j-i)*(height[i]<height[j]?height[i]:height[j])?(j-i)*(height[i]<height[j]?height[i]:height[j]):max;
           if(height[i]<=height[j]){
               i++;
           }else{
               j--;
           }
       }
        return max;
    }
}
看到这个题第一眼是懵逼的,然后发现了它的面积的计算公式其实就很容易了,不过就是较小的一侧高度乘以宽度,那么既然有边界并且两边都可以走,那么自然而然想到双指针,然后将每一次都走较小的一侧就可以了。

五、爬楼梯

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs

描述:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶

示例2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:35.3 MB, 在所有 Java 提交中击败了22.21%的用户

class Solution {
    public int climbStairs(int n) {
        if(n<=2){
            return n;
        }
        int i=1;
        int j=2;
        int num=3;
        for(int k=3;k<=n;k++){
            num=i+j;
            i=j;
            j=num;
        }
        return num;
    }
}
就本题而言仔细观察可以发现就是一个斐波那契数列,看题解中可以用数学公式直接做,不过我数学不太好不知道这个......

六、合并两个有序链表

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-sorted-lists

描述:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

在这里插入图片描述

示例1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例2:

输入:l1 = [], l2 = []
输出:[]

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:37.7 MB, 在所有 Java 提交中击败了73.16%的用户

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode listNode1=new ListNode();
        ListNode listNode2=listNode1;
        for(;l1!=null&&l2!=null;){
            if(l1.val<=l2.val){
                listNode1.next=l1;
                l1=l1.next;
             }else{
                listNode1.next=l2;
                l2=l2.next;
            }
            listNode1=listNode1.next;
        }
        if(l1==null){
            listNode1.next=l2;  
        }else{
            listNode1.next=l1;
        }
        return listNode2.next;
    }
}
这个没什么思考的,两个链表已经排好序了,所以直接依次将小的放入新建链表就可以了。如果两个链表长度不等,那么a先走完就直接将b全部放入。

七、加一

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/plus-one

描述:

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例1:

输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

示例2:

输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。

解决:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:37 MB, 在所有 Java 提交中击败了30.70%的用户

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i=digits.length-1;i>=0;i--){
            if(digits[i]==9){
                digits[i]=0;
            }else{
                digits[i]+=1;
                return digits;
            }
        }
        digits=new int[digits.length+1];
        digits[0]=1;
        return digits;
    }
}
看到这个题,马上就写了个digits[digits.length-1]+=1;return digits;直接提交,然后发现坑的是他还有进位问题.......这告诉我们要仔细审题。
进位是往前进的,所以我们得先知道后面才能算前面,所以自然而然需要从后往前遍历,如果等于9,则此位置为0就可,遍历前一位加一。如果是99这样的数,那么正确答案就是100这样的数,所以最后数组扩容,第一位置1就可。

总结

这是两年前还在刷力扣的时候打算写的简单题解系列的第二篇文章…结果把这事给忘了…刚发现这儿还有个草稿

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Magic171

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值