Leecode 题集

这篇博客详细介绍了LeetCode上的多个算法题目,包括两数相加、整数反转、回文数、罗马数字转整数等经典问题。博主提供了多种解法,如链表操作、双指针、贪心算法等,并分享了执行时间和内存消耗,帮助读者深入理解算法的实现和优化。
摘要由CSDN通过智能技术生成


声明:题、图源自Leecode:https://leetcode-cn.com/


Leecode

2:两数相加

原题:https://leetcode-cn.com/problems/add-two-numbers/
提示:要注意两个链表长度不一的情况
注意用例 [2,4,9] [5,6,4,9] 和 [9,9,9,9] [9,9,9,9,9,9,9,9]
解答1:利用新链表存储结果,超出时间限制。

/**
 * 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 addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null && l2 == null) {
            return null;
        }
        // l1和l2可能长度不同
        int sign=0; // 进位
        ListNode result=new ListNode(); // 结果链表
        ListNode p=result;
        // l1和l2相加
        while(l1 != null && l2 != null) {
            p=p.next=new ListNode();
            int sum=l1.val+l2.val+sign;
            // 有进位
            if(sum>9) {
                sign=1;
                sum-=10;
            }else {
                sign=0;
            }
            p.val=sum;
            l1=l1.next;
            l2=l2.next;
        }
        // l1为空
        while(l2 != null) {
            p=p.next=new ListNode();
            p.val=l2.val;
        }
        // l2为空
        while(l1 != null) {
            p=p.next=new ListNode();
            p.val=l1.val;
        }
        return result.next;
    }
}

解答2:运行时间 8 ms,内存消耗 39.1 MB

/**
 * 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 addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null && l2 == null) {
            return null;
        }
        ListNode result=l1;
        ListNode p1=l1,p2=l2;
        // 创建新链表会超出内存限制,因此采用原链表数据进行修改
        int sign=0; // 进位
        int sum=0;
        while(l1 != null && l2 != null) {
            sum=l1.val+l2.val+sign;
            if(sum>9) {
                sum-=10;
                sign=1;
            } else {
                sign=0;
            }
            // 更新l1中的值为和
            l1.val=sum;
            p1=l1;p2=l2;
            l1=l1.next;
            l2=l2.next;
        }
        // 后面用于判断是否需要拼接l1与l2
        boolean flag=false;
        //ListNode temp=flag?l2:null;
        ListNode temp=l2;
        // l2不为空
        while(l2 != null) {
            flag=true;
            // 有进位:更新值
            if(sign == 1){
                sum=l2.val+sign;
                sign=sum>9?1:0;
                l2.val=(sign==1)?sum-=10:sum;
            }
            // 指向当前的上一个
            p2=l2;
            l2=l2.next;
            System.out.println(p2.val+",");
        }
        // l1不为空,且有进位:更新值
        while(l1 != null) {
            if(sign == 1) {
                sum=l1.val+sign;
                sign=sum>9?1:0;
                l1.val=(sign==1)?sum-=10:sum;
            }
            // 指向当前的上一个
            p1=l1;
            l1=l1.next;
        }
        // 进位,但已经超出原来的长度
        if(sign == 1){
            ListNode last=flag?p2:p1;
            last.next=new ListNode(1);
        }
        if(flag) {
            // temp是链表2多出的部分
            p1.next=temp;
        }
        return result;
    }
}

7:整数反转

题目
题目:给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
解法:运行时间 34 ms,内存消耗 38.5 MB

class Solution {
    public int reverse(int x) {
        if(x==0){
            return 0;
        }
        String a=Integer.toString(x);
        int length=a.length();
        String result="";   //存放结果
        int save=0;
        int i=1;
        if(x>0){    //x为正数
            for(int j=0;j<length;i=i*10,j++){
                if(j==length-1){
                    save=x/i;
                    result=result+save;
                }else{
                    save=(x%(i*10))/i;
                    result=result+save;
                }
            }
            
            try{    //溢出
                save=Integer.parseInt(result);
            }catch(Exception e){
                return 0;
            }
            return save;
        }
        //当x<0,即x为负数的时候
        i=1;
        x=Math.abs(x);  //将x转换为正数
        for(int j=0;j<length-1;i=i*10,j++){
            if(j==length-2){
                save=x/i;
                result=result+save;
            }else{
                save=(x%(i*10))/i;
                result=result+save;
            }
        }
        try{    //溢出
            save=Integer.parseInt(result);
        }catch(Exception e){
            return 0;
        }
        return 0-save;
    }
}

9:回文数(不转换成字符串)

题目
在这里插入图片描述
解题:执行用时 20 ms ; 内存消耗 37.8 MB。

class Solution {
    public boolean isPalindrome(int x) {
        if(x<0){
            return false;
        }
        if(x>=0&&x<10){
            return true;
        }
        String s=x+"";
        int length=s.length();
        int j=1;int left;int right;int wei;
        for(int i=0;i<length/2;i++,j=j*10){
            wei=length-i;
            left=x%(int)(Math.pow(10,wei))/(int)(Math.pow(10,wei-1));
            right=x%(j*10)/j;
            if(left==right){
                continue;
            }else{
                return false;
            }
        }
        return true;
    }
}

13:罗马数字转整数

题目在这里插入图片描述
在这里插入图片描述
解题:执行用时 5 ms,内存消耗 38.4 MB。

class Solution {
    public int romanToInt(String s) {
        char c[]=s.toCharArray();   //将字符串s转换成字符数组
        int k[]=new int[c.length];  //存放每个字符对应的数值
        for(int i=0;i<c.length;i++){
            switch(c[i]){
                case 'I':k[i]=1;break;
                case 'V':k[i]=5;break;
                case 'X':k[i]=10;break;
                case 'L':k[i]=50;break;
                case 'C':k[i]=100;break;
                case 'D':k[i]=500;break;
                case 'M':k[i]=1000;break;
            }
        }
        int sum=0;  //存储计算结果
        //计算输入的值
        for(int i=0;i<c.length;i++){
            if(i==c.length-1){      //当前是最后一个字符
                sum=sum+k[i];
            }else{
                if(k[i]>=k[i+1]){   //正常情况,直接相加即可
                    sum=sum+k[i];
                }else{  //特殊:小的数字在大的数字左边
                    sum=sum-k[i];
                }
            }
        }
        return sum;
    }
}

15:三数之和

题目:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
在这里插入图片描述
提示:注意用例 [0,0,0] [0,0,0,0] [-1,0,1,0]
解答:双指针法。执行用时 1719 ms,内存消耗 42.2 MB。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result=new ArrayList<>();
        if(nums.length<3)   return result;
        // 排序,为了和结果顺序匹配
        Arrays.sort(nums);
        for(int i=0;i<nums.length && nums[i] <= 0;i++){
            // 该值已经比对过一次
            if(i>0 && nums[i] == nums[i-1]) {
                continue;
            }
            for(int j=i+1;j<nums.length;j++){
                int k=k=nums.length-1;
                // j与上一个值相等:跳过该数
                if(j>i+1 && nums[j] == nums[j-1]){
                    continue;
                }
                // 三个数之和大于0,k向前移动
                while(j<k && (nums[i]+nums[j]+nums[k])>0){
                    k--;
                    // 若k重复,再向前
                    while(j < k && k != nums.length-1 && nums[k] == nums[k+1]){
                        k--;
                    }
                }
                if(j >= k){
                    break;
                }
                // 三个数之和=0,同时j和k没有重复指向同一个数
                if((nums[i]+nums[j]+nums[k]) == 0){
                    List<Integer> current=new ArrayList<>();
                    current.add(nums[i]);
                    current.add(nums[j]);
                    current.add(nums[k]);
                    result.add(current);
                }
            }
        }
        return result;
    }
}

18:四数之和

题目:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
链接https://leetcode-cn.com/problems/4sum
解答:执行用时 6 ms ; 内存消耗 38.5 MB。
参照三数之和的解法,利用双指针。首先数组排序,确定第一位和第二位,剩下两位用两个指针移动,若大于目标值则移动右指针;若小于目标值则移动左指针。

    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res=new ArrayList<>();
        if(nums == null || nums.length < 4) {
            return res;
        }
        // 数组排序
        Arrays.sort(nums); 
        for(int i=0;i<nums.length-3;i++) {
            // 去除重复元素
            if(i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            // 若前四个数(当前数组中最小的值)相加大于目标值==>不存在结果集
            if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target) {
                break;
            }
            // 若当前值+最大的三个数小于目标值==>当前值不存在符合的结果集
            if(nums[i]+nums[nums.length-3]+nums[nums.length-2]+nums[nums.length-1] < target) {
                continue;
            }
            for(int j=i+1;j<nums.length-2;j++) {
                // 在本层循环:若上一个元素值与当前值相同,说明寻找过,跳过
                if(j > i+1 && nums[j] == nums[j-1]) {
                    continue;
                }
                // 若当前元素i+j+最大的两位数小于目标值==>当前j不存在符合的结果集
                if(nums[i]+nums[j]+nums[nums.length-1]+nums[nums.length-2] < target) {
                    continue;
                }
                // 若当前元素i+j+最小的两位大于目标值==>当前循环不存在结果
                if(nums[i]+nums[j]+nums[j+1]+nums[j+2] > target) {
                    break;
                }
                int k=j+1;
                int z=nums.length-1;
                while(k<z) {
                    int sum=nums[i]+nums[j]+nums[k]+nums[z];
                    if(sum == target) {
                        // 加入结果中
                        List<Integer> cur=new ArrayList<>();
                        cur.add(nums[i]);
                        cur.add(nums[j]);
                        cur.add(nums[k]);
                        cur.add(nums[z]);
                        res.add(cur);
                        // 去重
                        while(k<z && nums[k] == nums[k+1]) {
                            k++;
                        }
                        // 跳出循环的时候:下一个k才是与当前不重复的,之前都是重复的
                        k++;
                        while(k<z && nums[z] == nums[z-1]) {
                            z--;
                        }
                        z--;
                    }else if(sum > target) {
                        // 当前值大于目标值,应该减小:当前z最大,移动z
                        z--;
                    }else if(sum < target) {
                        // 当前值小于目标值,应该增大:当前z最大,移动k
                        k++;
                    }
                }
            }
        }
        return res;
    }

19:删除链表的倒数第 N 个结点

题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
在这里插入图片描述
提示

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
通过次数363,684提交次


来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list

解题

    public ListNode removeNthFromEnd(ListNode head, int n) {
        //创建一个链表指向head,多了一个头结点是0。保证当删除头结点时也可以正常删除。
        ListNode copy=new ListNode(0,head);
        //一个指针p1指向头结点
        ListNode p1=copy;
        //一个指针p2指向与p1相距n个节点的结点,即最后p1会指向要删除结点的上一位。
        ListNode p2=head;
        for(int i=0;i<n;++i){
            //p2向后移n-1次
            p2=p2.next;
        }
        //循环遍历,直到p2指向null(即p2上一位是尾结点)
        while(p2!=null){
            //p1,p2每次向后移一位
            p1=p1.next;
            p2=p2.next;
        }
        //此时p1指向的是倒数第n个节点的上一个节点
        //删除第n个节点
        p1.next=p1.next.next;
        //去除头节点0
        return copy.next;
    }

20:有效的括号

题目
在这里插入图片描述

解法:执行用时8ms,内存消耗36.7MB

class Solution {
    public boolean isValid(Str
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值