Leecode_Java题学习总结

本文精选LeetCode上的经典算法题目,包括两数之和、链表相加、最长无重复子串等,提供详细的Java代码解答及思路分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leecode算法题(Java)


1.给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。来源:力扣(LeetCode)

示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

题解
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int len =nums.length;
        for(int i=0;i<len-1;i++){
            for(int j=i+1;j<len;j++){
                if(nums[i]+nums[j]==target){
                    return new int[] {i,j};//这里是Java中返回int型数组的方法
                }
            }
        }
        return null;//这里要特别注意
    }
}
2.给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
来源:力扣(LeetCode)

题解
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int sum = 0;//进行链表对应位置的每一步计算
        ListNode first = new ListNode(0);//新建一个初值为0的链表
        ListNode t=l1;//指向链表1
        ListNode p=l2;//指向链表2
        ListNode cur = first;//新建一个指针,指向first链表
        while(t!=null || p!=null){
            if(t!=null){
                sum+=t.val;//sum将该t位置的val(int)值,添加进去
                t=t.next;
            }
            if(p!=null){
                sum+=p.val;//sum将该p位置的val(int)值,添加进去
                p=p.next;
            }
            cur.next=new ListNode(sum%10);//下一结点的数值为sum%10
            cur=cur.next;//再次指向cur指针的下一结点,也可以说指向cur指针标记first链表位置的,下一first位置
            sum=sum/10;//sum除10,结果作为下一sum的起始数值
        }
        if(sum>0){
            cur.next=new ListNode(1);//如果遍历到最后,sum还不为0,则说明最后一位进位了,因此,再次开辟空间,给新的空间赋值1。
        }
        return first.next;//该位置是.next的原因:因为新建first链表时,给first的初位置赋值为0,而从未对该位置进行操作,因此,当返回结果数值时,应该从first链表的第二位开始返回。
    }
}
3.给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

题解:
package leecode_Test;

import java.util.Scanner;

public class test1 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        System.out.println(lengthOfLongestSubstring(str));
    }
    public static int lengthOfLongestSubstring(String s) {
        int i = 0;
        int flag = 0;
        int length = 0;
        int result = 0;
        while (i < s.length()) {
            int pos = s.indexOf(s.charAt(i),flag);//indexOf作用:第一个参数:指定的变量。第二个参数:指定的位置
            if (pos < i) {//证明存在重复字符
                if (length > result) {
                    result = length;//result应该是记录最大不重复的字符串长度
                }
                if (result >= s.length() - pos - 1) {
                    return result;//该步的作用是:如果记录的最大长度(result)大于等于后续剩余字符长度,那么,就说明,result已为最大字符长度,则直接返回result结果
                }
                length = i - pos - 1;//取两个重复字符中间的字符个数,而减一的目的是为了:让辨别结点从第一位重复元素的下一位开始识别
                flag = pos + 1;//记录第一位重复字符的下一位的位置
            }
            length++;//该步length可以自然自增的原因是:1、当有重复字符时,上一步length是两个重复字符的中间字符个数,但是,仔细考虑
            //中间字符应该为每个独立,各不相同,因此,将前面的重复字符去掉后,后面的重复字符又补了进来,所以,length的值应该自增加一
            i++;//向下依次遍历字符串中的字符
        }
        return length;//考虑字符串内没有重复字符,做的预处理
    }
}
7.给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123
输出: 321
示例 2:

输入: -123
输出: -321
示例 3:

输入: 120
输出: 21

注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

题解:
package leecode_Test;

import java.util.Scanner;

public class test5 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int num =sc.nextInt();
        System.out.println(reverse(num));
        //Java中int类整数的最大值是:2的31次方-1
        //最大值:2147483647
        //最小值:-2147483648
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
    }
    public static int reverse(int x) {
        long y = 0;
        while (x != 0) {
            y = y * 10 + x % 10;
            x /= 10;
        }
        if (y > Integer.MAX_VALUE || y < Integer.MIN_VALUE)
            return 0;
        return (int) y;
    }
}
13.罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class test13_1 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String string = sc.next();
        System.out.println(method(string));
    }
    public static int method(String s){
        Map<String,Integer> map = new HashMap<>();
        map.put("I",1);
        map.put("IV",4);
        map.put("V",5);
        map.put("IX",9);
        map.put("X",10);
        map.put("XL",40);
        map.put("L",50);
        map.put("XC",90);
        map.put("C",100);
        map.put("CD",400);
        map.put("D",500);
        map.put("CM",900);
        map.put("M",1000);
        int num=0;
        for(int i=0;i<s.length();){
            if(i+1<s.length()&&map.containsKey(s.substring(i,i+2))){
                num+=map.get(s.substring(i,i+2));
                i+=2;
            }else{
                num+=map.get(s.substring(i,i+1));
                i++;
            }
        }
        return num;
    }
}
14.编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:

输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。

public class test14 {
    public static void main(String[] args){
        String[] strings = new String[5];
        Scanner sc = new Scanner(System.in);
        strings[0]=sc.next();
        strings[1]=sc.next();
        strings[2]=sc.next();
        strings[3]=sc.next();
        strings[4]=sc.next();
        System.out.println(longestCommonPrefix(strings));
    }
    public static String longestCommonPrefix(String[] strs) {
       if(strs.length==0 || strs==null){
           return "";
       }
       for(int i=0;i<strs[0].length();i++){
           char c = strs[0].charAt(i);
           for(int j=1;j<strs.length;j++){
               if(i==strs[j].length() || strs[j].charAt(i)!=c ){
                   return strs[0].substring(0,i);
               }
           }
       }
       return strs[0];
    }
}
思路

该题算法是:以第一个字符串为基础,用以与其他字符串进行比较,获得公共前缀,返回结果为第一个字符串的截取结果。

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

示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

题解:
public class test21_3 {//利用递归的方法
    public class ListNode{
        int val;
        ListNode next;
        ListNode(int x){
            val = x;
        }
    }
    public static ListNode merge(ListNode l1,ListNode l2){
        if(l1==null){//若l1为空则返回l2
            return l2;
        }
        else if(l2==null){//若l2为空则返回l1
            return l1;
        }
        else if(l1.val<l2.val){
            l1.next=merge(l1.next,l2);
            return l1;
        }
        else{
            l2.next=merge(l1,l2.next);
            return l2;
        }
    }
}
思路:

链表l1:1->3
链表l2:2->4
为例
首先:l1:1->
l2:2->
l1:3->
l2:4
最后,由于l1中数据已空,则返回4到l1的3->4中,然后3->4返回到l2中,2->3->4,最后,返回到l1中,1->2->3->4。如果没有看懂的话,可以用1,2,3,4,自己试一下。

实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例1:
输入: haystack = “hello”, needle = “ll”
输出: 2
示例2:
输入: haystack = “aaaaa”, needle = “bba”
输出: -1

题解
import java.util.Scanner;

public class test_28 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        String str2 = sc.next();
        System.out.println(strStr(str1,str2));
    }
    public static int strStr(String haystack, String needle) {
        int strLen = haystack.length(), subLen = needle.length();
        if (subLen == 0) return 0;
        if (strLen == 0) return -1;
        // 构建状态机
        int[][] FSM = new int[subLen][256];
        int X = 0, match = 0;
        for (int i = 0; i < subLen; i++) {
            match = (int) needle.charAt(i);
            for (int j = 0; j < 256; j++) {
                // 当前状态 + 匹配失败字符 = 孪生词缀状态 + 匹配字符
                FSM[i][j] = FSM[X][j];
            }
            FSM[i][match] = i + 1;
            if (i > 1) {
                // 下一孪生前缀状态 = X + match
                X = FSM[X][match];
            }
        }
        // 匹配子串
        int state = 0;
        for (int i = 0; i < strLen; i++) {
            state = FSM[state][haystack.charAt(i)];
            if (state == subLen) {
                return i - subLen + 1;
            }
        }
        return -1;
    }
}

主要运用数据结构中的KMP算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值