LeetCode代码刷题(1~8)

目录

1. 题目:两数之和

2. 题目:两数相加(链表)

3. 题目:无重复字符的最长字串 

4. 题目:寻找两个正序数组的中位数

5. 题目:最长回文子串

6. 题目:寻找两个正序数组的中位数(二)

7. 题目:字符串转换整数 (atoi)

8. 题目:整数反转


1. 题目:两数之和

题目:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

代码:
import java.util.HashMap;

public class TwoSum {
    //暴力法
    public static int[] twoSum(int[] array, int target){
        int[] result = new int[2];
        for(int i=0; i<array.length; i++){
            for(int j=i+1; j<array.length; j++){
                if(array[i] + array[j] == target){
                    result[0] = i;
                    result[1] = j;
                    return result;
                }
            }
        }
        return result;
    }

    //哈希表法
    public static int[] twoSum2(int[] array, int target){
        HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
        int[] result = new int[2];
        int rest = 0;

        for(int i=0; i<array.length; i++){
            hashMap.put(array[i], i);
        }

        for(int i=0; i<array.length; i++){
            rest = target - array[i];
            if(hashMap.containsKey(rest) && hashMap.get(rest) != i){
                result[0] = i;
                result[1] = hashMap.get(rest);
                return result;
            }
        }
        return result;
    }


    public static void main(String[] args) {
        int[] array = {21,5,4,1,8,3};
        int target = 7;
        int[] result = twoSum2(array, target);
        System.out.println("满足条件的数组下标为:" + result[0]+", "+result[1]);
    }
}

2. 题目:两数相加(链表)

题目:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

分析:

该题是经典的两数相加问题,数字以逆序存储在链表中,也就是链表的第一位就是数字的个位,所以可以直接按照链表顺序依次进行相加,

一个需要注意的点就是,每次相加时,需要同时加上进位carry,然后如果此次相加结果大于10,则取个位数字,并将进位保留到下一次链表相加。

简单来讲,每个链表结点相加规则如下:

数值:(l1.val + l2.val + carry) % 10

进位:(l1.val + l2.val + carry) / 10

/** 新建一个ListNode类,然后调用

* 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; }

* }

*/

代码:

import java.util.List;



public class AddTwoNumbers {

    //常规解法

    public static ListNode addTwoNumbers(ListNode l1, ListNode l2){

        ListNode head = null;

        ListNode tail = null;

        int carry = 0;



        while(l1 != null || l2 != null){

            int listNode1 = 0;

            if(l1 != null){

                listNode1 = l1.val;

                l1 = l1.next;

            }



            int listNode2 = 0;

            if(l2 != null){

                listNode2 = l2.val;

                l2 = l2.next;

            }



            int sum = listNode1 + listNode2 + carry;

            if(head == null){

                head = tail = new ListNode(sum%10);

            }else {

                tail.next = new ListNode(sum%10);

                tail = tail.next;

            }

            carry = sum / 10;

        }

        if( carry > 0){

            tail.next = new ListNode(carry);

        }

        return head;

    }


    //递归解法

    public static ListNode addTwoNumbers2(ListNode l1, ListNode l2, int carry){

        if(l1 == null && l2 == null && carry == 0){

            return null;

        }

        int nextNode1 = 0;

        int nextNode2 = 0;

        if(l1 != null){

            nextNode1 = l1.val;

            l1 = l1.next;

        }

        if(l2 != null){

            nextNode2 = l2.val;

            l2 = l2.next;

        }

        int sum = nextNode1 + nextNode2 + carry;

        ListNode result = new ListNode(sum % 10);

        result.next = addTwoNumbers2(l1, l2, carry); //递归

        return result;

    }


    //主函数

    public static void main(String[] args) {

        ListNode l1 = new ListNode(0); //创建首节点

        ListNode nextNode1; //创建下一个节点

        nextNode1 = l1; //初始化下一个节点,让其指向首节点

        for(int i=1; i<3; i++){

            ListNode newNode = new ListNode(i); //创建新的结点

            nextNode1.next = newNode;   //连结新节点

            nextNode1 = nextNode1.next; //节点后移

        }



        ListNode l2 = new ListNode(0);

        ListNode nextNode2;

        nextNode2 = l2;

        for(int j=5; j>2; j--){

            ListNode newNode = new ListNode(j);

            nextNode2.next = newNode;

            nextNode2 = nextNode2.next;

        }


        ListNode result = addTwoNumbers2(l1, l2, 0);

        result = result.next;

        while(result != null){

            System.out.print(result.val + " ");

            result = result.next;

        }

    }

}

3. 题目:无重复字符的最长字串 

题目:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

思路:

HashSet不能存储重复元素;

HashSet不确保插入顺序;

HashSet是非线程安全的。

把出现过的字符都放入 set 中,遇到 set 中没有的字符就加入 set 中并更新结果 res,然后右边界 +1。如果遇到重复的,则删除 set 中下标为左边界的字符,即遇到一个重复字符,则删除一个 set 中的字符,然后左边界 +1:

代码:

import java.util.HashSet;


public class LengthOfLongestSubstring {

    public static int lengthOfLongestSubstring(String str){

        int left = 0;

        int right = 0;

        int length = 0;

        HashSet<Character> hashSet = new HashSet<Character>();


        while (right < str.length()){

            if(!hashSet.contains(str.charAt(right))){

                hashSet.add(str.charAt(right));

                right++;

                length = Math.max(length, hashSet.size()); //始终保存出现过的最长的(没有重复字符的)子字符串

            } else {

                hashSet.remove(str.charAt(left)); //如果重复的不是最左边的字符,这个移除之后,进入下一轮循环,hashSet中依然含有重复的字符,会再一次走这条路,移除,直至移除掉重复的字符

                left++;

            }

        }

        return length;

    }


    public static void main(String[] args) {

        String str = "abcdbc";

        System.out.println("最长字串的长度为:"+lengthOfLongestSubstring(str));

    }

}

4. 题目:寻找两个正序数组的中位数

题目:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出并返回这两个正序数组的 中位数 。

代码:

public class FindMedianSortedArrays {

    public static double findMedianSortedArrays(int[] num1, int[] num2){

        int l1 = num1.length;

        int l2 = num2.length;

        int length = l1 + l2;

        int[] combineArray = new int[length];


        int i=0, j=0, k=0;

        while(i<l1 && j<l2){

            if(num1[i] < num2[j]){

                combineArray[k++] = num1[i++];

            }else {

                combineArray[k++] = num2[j++];

            }

        }

        while (i<l1){

            combineArray[k++] = num1[i++];

        }

        while (j<l2){

            combineArray[k++] = num2[j++];

        }

        if(length % 2 == 0){

            return (combineArray[length/2 -1] + combineArray[length/2])/2.0;

        }else {

            return combineArray[length/2];

        }

    }

    public static void main(String[] args) {

        int[] num1 = {1,2};

        int[] num2 = {3,4};

        double result = findMedianSortedArrays(num1, num2);

        System.out.println("两个正序数组的中位数为: " + result);

    }

}

5. 题目:最长回文子串

题目:给你一个字符串 s,找到 s 中最长的回文子串。 示例 1: 输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。

思路:

回文字符串:是一个正读和反读都一样的字符串。回文中心的两侧互为镜像。 假定从字符串的每个字符开始,都有回文数,遍历整体字符串的长度,算出每个字符回文数的长度,最后比较输出最长 如果假设每个字符都存在回文数,那考虑这个字符奇数回文数的情况和偶数个回文数的情况

代码:

public class LongestPalindrome {

    public static void main(String[] args) {
        String str = "abefeba";
        String palindrome = longestPalindrome(str);
        System.out.println(palindrome);
    }

    public static String longestPalindrome(String s){
        String result = ""; //用以保存最长回文子串

        if(s.length() < 2){ //如果整个字符串长度小于2,则直接返回
            return s;
        }

        for(int i=0; i<s.length(); i++){  //假定从字符串的每个字符开始,都有回文数,遍历整体字符串的长度
            result = findPalindrome(s, i, i, result); //当前字符的回文串是奇数的情况
            result = findPalindrome(s, i, i+1, result);   //当前字符的回文串是偶数的情况
        }
        return result;
    }

    public static String findPalindrome(String s, int before, int after, String result){
        while(before>=0 && after<s.length() && (s.charAt(before) == s.charAt(after))){ //满足回文条件,则往左右扩展
            before--;
            after++;
        }
        //上面退出while的时候,before多减了1,after多加了1。所以要先复原最后满足回文的before和after值。
        if(((after-1)-(before+1)+1) > result.length()){
            result = s.substring(before+1, after); //如果新的回文子串更长,则替换result。subString(i,j) 截取子字符串,包含起始索引,不包含结束索引
        }
        return result;
    }
}

6. 题目:寻找两个正序数组的中位数(二)


具体要求:

给定两个大小分别为 m 和 n 的正序(从小到大)数组nums1 和nums2。

请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。


代码演示:

/**
 * 寻找两个正序数组的中位数
 * 给定两个大小分别为 m 和 n 的正序(从小到大)数组nums1 和nums2。请你找出并返回这两个正序数组的 中位数 。
 *
 * 算法的时间复杂度应该为 O(log (m+n)) 。
 */
 
package com.my.test;
 
//该算法的时间复杂度为0(m+n)
public class FindMediaNumber {
 
    public static void main(String[] args) {
        int[] num1 = {1,3,5,7,9};
        int[] num2 = {2,4,6};
        System.out.println(FindMediaNumber(num1, num2));
    }
 
    public static double FindMediaNumber(int[] num1, int[] num2){
        int m = num1.length;
        int n = num2.length;
        double media_num;
 
        //如果数组1为空,则直接返回数组2的中位数
        if(m == 0){
            if(n%2 == 0){
                media_num = (num2[n/2-1]+num2[n/2])/2.0;
            } else {
                media_num = num2[n/2];
            }
            return media_num;
        }
 
        //如果数组2为空,则直接返回数组1的中位数
        if(n == 0){
            if(m%2 == 0){
                media_num = (num1[m/2-1]+num1[m/2])/2.0;
            } else {
                media_num = num1[m/2];
            }
            return media_num;
        }
 
        //合并两个数组
        int[] combine = new int[m+n];
        int count = 0;
        int i = 0;
        int j = 0;
        while(count != (m+n)){
            if (i == m) {
                while(j != n){
                    combine[count++] = num2[j++];
                }
                break;  //已完成合并,跳出while循环
            }
            if(j == n){
                while (i != m){
                    combine[count++] = num1[i++];
                }
                break;  //已完成合并,跳出while循环
            }
 
            //从两个数组中遍历元素,进行对比,将较小的元素放入新数组
            if(num1[i] < num2[j]){
                combine[count++] = num1[i++];
            }else {
                combine[count++] = num2[j++];
 
            }
        }
 
        //完成数组合并后,从新数组中查找中位数
        if((m+n)%2 == 0) {
            media_num = (combine[(m + n) / 2 - 1] + combine[(m + n) / 2]) / 2.0;
        } else {
            media_num = combine[(m+n)/2];
        }
 
        return media_num;
    }
 
}

运行结果:

4.5

Process finished with exit code 0

7. 题目:字符串转换整数 (atoi)

具体要求:
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

(1)读入字符串并丢弃无用的前导空格
(2)检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
(3)读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串其余部分将被忽略。
(4)将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
(5)如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
(6)返回整数作为最终结果。

 

注意:

本题中的空白字符只包括空格字符 ' ' 。

除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

代码演示:
补充知识点:

(1)在JAVA中,因为对char类型字符运行时,直接当做ASCII表中对应的整数来对待。所以char可以直接转成int,得到的就是ASCII中对应的数字。所以不能直接转成int;所可以直接将char转成String,再转成int。JAVA中,char是一个基本类型(基本类型只能由基本类型强制转换),String是一个引用类型。推荐使用valueOf这个方法进行转换。

package com.my.test;
 
public class MyAtoi {
 
    public static void main(String[] args) {
        String str = " 666 words and 987";
        System.out.println("原始字符串为:" + str);
        System.out.print("转换后的数值为: ");
        System.out.println(myAtoi(str));
    }
 
    public static int myAtoi(String str){
        //字符串为空的处理
        if(str==null || str.equals("") || str.trim().equals("")){
            return 0;
        }
 
        char[] chars = str.trim().toCharArray();  //字符串去掉前后的空格之后,转为字符数组
        int index = 0;
        boolean judge = true; //标识正数或负数
        if(chars[0]=='+' || chars[0]=='-'){ //去除空格后,如果第一位是符号位:正号负号
            if(chars[0]=='-'){
                judge = false;
            }
            index++;
        }
 
 
        int sum = 0;
        //int count = 0;
        while(index<chars.length && Character.isDigit(chars[index])){  //除了符号位之外,开始遍历字符数组,直到遍历数组结束或者遇到非数值
            int num = chars[index] - '0'; //char转为int的一种方式
            //int num = Integer.parseInt(String.valueOf(chars[index]));  //char转为int的另一种方式
            if(sum > (Integer.MAX_VALUE-num)/10){   //判断加上该数字后是否超过最大值
                if(judge){
                    return Integer.MAX_VALUE;
                }else {
                    return Integer.MIN_VALUE;
                }
            }
            //如果没超过最大值,需要求和处理
            sum = sum*10 + num;
            index++;
            //count++;
        }
        //如果符号位是负号,则最后的结果是负数
        if(!judge){
            sum = -sum;
        }
        return sum;
    }
}

运行结果:

原始字符串为: 666 words and 987
转换后的数值为: 666

Process finished with exit code 0

8. 题目:整数反转

具体要求:

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

代码演示:

package com.my.test;

public class IntReverse {

    public static void main(String[] args) {
        int num = -123;
        System.out.print("原始数值为:");
        System.out.println(num);
        System.out.print("反转后的数值为:");
        System.out.println(intReverse(num));

    }

    public static int intReverse(int num){
        long result = 0;
        long min = -2147483648;  //有符号整数的范围 [−231,  231 − 1], 2的31次幂
        long max = 2147483647;

        //使用Java里的StringBuffer类,该类中提供反转字符串的方法,先将整数转换为字符串,然后进行反转操作,再转换回整数后输出
        StringBuffer sb = new StringBuffer();
        sb.append(num); //整数转为字符串

        if(num > 0){
            sb.reverse(); //反转字符串
            for(int i=0; i<sb.length(); i++){  //字符串转为整数
                int n = sb.charAt(i) - '0';
                result = result*10 + n;
            }
            if(result<max){  //如果整数没超过最大值
                return (int) result;
            } else {
                return 0;
            }
        } else if(num < 0){
            sb.reverse();  //反转字符串
            for(int j=0; j<sb.length()-1; j++){  //字符串转为整数
                int m = sb.charAt(j) - '0';
                result = result*10 + m;
            }
            if((0-result)>min){   //如果整数没小于最小值
                return (int) (0-result);
            } else {
                return 0;
            }
        } else {
            return 0;
        }
    }
}

运行结果:

原始数值为:-123
反转后的数值为:-321

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值