力扣题目 第一周

力扣题目

  • 第一周 2021.3.11-2021.3.20
完成情况

在这里插入图片描述


3.12
/*
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

**你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。**

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
*/

//new一个数组,遍历,看头+尾是否=target,有则return
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        for (int i = 0; i < nums.length; i++) {
            for (int j = nums.length - 1; j > i; j--) {
                if (nums[i] + nums[j] == target){
                    result[0] = i;
                    result[1] = j;
                    break;
                }
            }
        }
        return result;
    }
}

3.13
/*
2. 两数相加
**给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。**

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

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

示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
*/

/**
 * Definition for singly-linked list.
 *ListNode类有val属性和next属性
 * 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; }
 * }
 */

//ListNode是一个带有val属性和next属性的类
//他不断传入参数l1和l2直到传入的值为空
//通过对两个参数和进位的直接相加,就可的出计算的结果,最后判断进位是否还==0,否则指定下一位的值为进位值
class Solution {
    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //创建两个ListNode类型的对象
        ListNode head = null, tail = null;
        int carry = 0;

        //tail.next:下一位
        //while直到两个链表都为空
        while (l1 != null || l2 != null) {
            //判断是否为空,是则 赋值 0
            int n1 = l1 != null ? l1.val : 0;
            int n2 = l2 != null ? l2.val : 0;
            //计算链表每一位的值
            int sum = n1 + n2 + carry;
            //当链表头为空时,将其个位数赋值到其中(计算第一个数时用到)
            if (head == null) {
                head = tail = new ListNode(sum % 10);//个位数
            } else {//否则则进位并赋值
                tail.next = new ListNode(sum % 10);//个位数
                tail = tail.next;
            }

            carry = sum / 10; //进位

            //两个链表同时进位
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        //当while结束但是carry大于0时,说明有进位,则再进一位
        if (carry > 0) {
            tail.next = new ListNode(carry);
        }
        //返回链表
        return head;
    }

}

3.14
/*
3. 无重复字符的最长子串
**给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。**

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 3:

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

*/

//新建一个新的集合,将不重复的字符串放入,若遍历后发现重复,则删除头,直到第一个重复元素删除掉为止
//用set集合是因为set不保存重复字符,并继承Collection接口,可提供添加删除等方法,且长度可自由变换
class Solution {
    public static int lengthOfLongestSubstring(String s) {
        // 哈希集合,记录每个字符是否出现过
        Set<Character> occ = new HashSet<Character>();
        int n = s.length();
        // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        int rk = -1, ans = 0;
        for (int i = 0; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格,移除一个字符,直到相同元素移除完为止
                occ.remove(s.charAt(i - 1));
            }
            //通过contains()方法,循环查找是否有与occ哈希表相同的元素,有则跳过,回到if循环中删除第一个元素,无则添加元素到occ中
            //循环条件,不超过字符串长度,并且没有出现occ中有的元素,若有,则跳出循环
            while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                // 将元素添加到occ集合中
                occ.add(s.charAt(rk + 1));
                rk++;
            }
            // 判断是否为最长字符串
            ans = Math.max(ans, rk - i + 1);
        }
        return ans;
    }
}

3.15
/*
4. 寻找两个正序数组的中位数
**给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。**

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
*/

//以下做法条理清晰,自行解读
//利用数组,并使用System类的arraycopy方法追加数组
class Solution {
     public static double findMedianSortedArrays(int[] nums1, int[] nums2) {

        int targetlong = nums1.length+nums2.length;
        int[] target = new int[targetlong];
        int mid1;
        int mid2;
        double reslut = 0;
        //1.判断输入的数组是否为空

        //2.新建数组   target  数组追加数组
        System.arraycopy(nums1,0,target,0,nums1.length);
        System.arraycopy(nums2,0,target,nums1.length, nums2.length);

        //3.数组排序
        Arrays.sort(target);

        //4.判断target数组长度是否为偶数
        if (targetlong % 2 == 0){
            mid1 = targetlong / 2;
            mid2 = mid1 - 1;
            reslut = (double) (target[mid1] + target[mid2])/2;
        }else if (targetlong % 2 != 0){
            mid1 = targetlong / 2;
            reslut = (double)target[mid1];
        }

        return reslut;
    }
}

3.16
/*
5. 最长回文子串
**给你一个字符串 s,找到 s 中最长的回文子串。**

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"
*/

//通过嵌套for循环,实现对数组的每个数进行比较,同时增加条件是最长的回文子串,逻辑相对简单,但实现较为复杂。
class Solution {
    public String longestPalindrome(String s) {

        //1.只有一个字符串直接返回
        if (s.length()<2){
            return s;
        }

        //2.转换成数组
        char[] ans = s.toCharArray();

        int begin = 0;
        int maxlong = 1;

        //3.遍历,最后一位不需要遍历
        for (int i = 0; i < ans.length-1; i++) {
            for (int j = i+1; j < ans.length; j++) {
                //3.1比较maxlong是否是最长的,不是则没必要比了
                if (j-i+1 > maxlong && judge(ans,i,j)){
                    //如果传回来的是true
                    begin = i;//起始值
                    maxlong = j-i+1;//起始值到末尾的长度
                }
            }
        }
        //4.new一个数组进行输出
        char[] res = new char[maxlong];
        for (int i = 0; i < maxlong; i++) {
            res[i] = ans[begin];
            begin++;
        }

        return new String(res);
    }

    //3.1判定是否是会问子串
    public boolean judge(char[] ans,int left, int right){
        while (left < right){
            //3.2遍历两个重复数之间是否都处于对称状态
            //不是则输出false,若直到left=right都相等,则输出true
            if (ans[left] != ans[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

3.17
/*
6. Z 字形变换
**将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。**

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);
 
示例 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
*/

//通过判断x是否==0或者==长度-1,将每一个字符按顺序放入numRows个数组中,最后按顺序合并成字符串
//使用StringBuilder的原因:
//他是可改变字符串,通过append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列
//并且速率比String快的多
class Solution {
    public String convert(String s, int numRows) {
        int x = 0;
        int flag = 1;
        //1.判断是否有字符,无则返回s
        if (s.length() == 0 || s.toCharArray() == null ||numRows == 1) return s;

        //2.new一个长度为numRows的类型为StringBuilder的字符数组
        StringBuilder[] sb = new StringBuilder[numRows];
        for (int i = 0; i < sb.length; i++) {
            //3.在里面再创建一个StringBuilder类型的数组,相当于{{},{},{}}
            sb[i] = new StringBuilder();
        }

        //4.通过判断x是否等于0或者是否=长度-1   分别存放进不一样的数组中
        for (char c : s.toCharArray()) {
            sb[x].append(c);
            x = x+flag;
            if (x == 0 || x == numRows-1){
                flag = -flag;
            }
        }
        
        //5.创建一个StringBuilder类型对象    
        StringBuilder res = new StringBuilder();

        //6.将三个合并在一起
        for (int i = 0; i < sb.length; i++) {
            res.append(sb[i]);
        }

        return new String(res);
    }
}

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

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

**假设环境不允许存储 64 位整数(有符号或无符号)。**
(本题解法忽视这个提示,当然也提供了判断[−2^31,  2^31 − 1]的方法,请自行参照)

示例 1:

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

输入:x = -123
输出:-321
*/

//本人做法,相对长,且运行速度较慢,可自行参考答案
//重点是如何将数字反转的计算:result = (int) (yu*Math.pow(10,i-1)) + result;
class Solution {
    public int reverse(int x) {

        int i = 0;
        long result = 0;
        int yu = 0;
        int reslong = 0;

        if (x == 0){ return x;}

        //1.判断结尾是否有0,并去掉后面的0
        if (x%10 == 0){
            x = x/10;
        }

        //2.得出把后面0除掉得结果
        int number = x;

        //3.计算是多少位数
        while (number != 0){
            number=number/10;
            i++;
        }
        reslong = i;

        //4.直接计算出结果
        for (int j = 0; j < reslong; j++) {
            yu = x%10;
            result = (int) (yu*Math.pow(10,i-1)) + result;
            x = x/10;
            i--;
        }

        System.out.println(result);

        //通过类型强制转换得出是否超过[−2^31,  2^31 − 1]范围
        return (int)result == result ? (int) result : 0;
    }
}

/*
**判断是否超过	2^31 − 1
 (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10))
 
 **判断是否超过	−2^31
 (result < Integer.MIN_VALUE / 10 || (result == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10)))
*/

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

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

**
读入字符串并丢弃无用的前导空格

检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。

读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。

将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。

如果整数数超过 32 位有符号整数范围 [−2^31,  2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被固定为 −231 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1 
**

注意:

本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:

输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"42"(读入 "42")
           ^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。
*/

//以下做法条理清晰,自行解读,就是简单的对字符串进行筛选,并无复杂计算
class Solution {
    public int myAtoi(String s) {

        int res = 0;
        int index = 0;  //下标
        //1.转换字符串
        int length = s.length();
        char[] ans = s.toCharArray();

        //2.统计他的前置空格' '
        while (index < length && ans[index] == ' '){
            index++;
        }

        //判断是否为空的字符串
        if (index == length){
            return 0;
        }

        //3.查看其第一个字符是+还是-
        int sign = 1;
        if (ans[index] == '+'){
            index++;
        }
        else if (ans[index] == '-'){
            sign = -1;
            index++;
        }

        //4.统计后面的数
        while (index < length){
            char first = ans[index];
            //4.1判断是否为数字,不是则直接跳出
            if (first > '9' || first < '0'){
                break;
            }
            //4.2判断是否大于2的31次方-1(符号占一位)
            if (res > Integer.MAX_VALUE/10 || res == Integer.MAX_VALUE/10 && (first-'0') > Integer.MAX_VALUE%10){
                return Integer.MAX_VALUE;
            }
            if (res < Integer.MIN_VALUE/10 || res == Integer.MIN_VALUE/10 && (first-'0') > -(Integer.MIN_VALUE%10)){
                return Integer.MIN_VALUE;
            }
            //5.计算res等于多少
            res = res*10 + sign*(first-'0');
            index++;
        }
        return res;
    }
}

3.20
/*
9. 回文数
**给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。**

**回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
 
示例 1:

输入:x = 121
输出:true
示例 2:

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
*/

//我的思路正确,但方法较为复杂,好像有更简单的方法,可以看答案
//将x对半分成前面部分和后面部分,比较前面和后面的数字是否大小相等!
class Solution {
     public boolean isPalindrome(int x) {

        //1.判断是否为(负数,最后一位为0的非个位数,除了0之外,都是非回文整数)
        if (x<0 || x%10 == 0 && x != 0){
            return false;
        }

        //2.个位数则直接输出x
        if (x>=0 && x<=9){
            return true;
        }

        int number = x;
        int length = 0;
        //3.计算有多少位数
        while (number != 0){
            number = number/10;
            length++;
        }
        //这里可以用Integer类进行包装直接得出length

        //4.分成两个数,并把后面的数调转
        int halflength = 0;
        halflength = length/2;

        //5.前面的数
        int befor = (int) (x/Math.pow(10,halflength));

        //6.后面的数
        int behind = 0;
        int number2 = x;
        int halflength2 = halflength;
        if (length % 2 == 0){
            halflength2 = halflength-1;
        }
        while (halflength >= 0) {
            behind = (int) ((number2 % 10) * Math.pow(10, halflength2) + behind);
            number2 = number2/10;
            halflength--;
            halflength2--;
        }

        //比较前后两个数的大小是否相等
        if (befor == behind){
            return true;
        }
        return false;
    }
}
  • 以上为本人 “奋进的叻叻” 第一个星期的算法题目练习,每周周日会进行总结,以上代码均为自己所写,或有参考会做记录,并重新手写一遍,以加深记忆。

  • (并不是所有解答均为最有效方法,只是本人最熟悉的方法,以后会更加专注于代码效率的提升)

  • 第一周练习,思路并不清晰,注释并不完善条理,将会不断提升

  • 或许有错误的地方,请帮忙指出,谢谢。

  • 题目以及部分解答出自力扣

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值