LeetCode笔记

LeetCode

前言:知道的越多,不知道的就越多。
持续学习
始于:2021/08/05

gitee地址:gitee
开始慢慢补齐自己的短板-算法。

1、两数之和

题目:

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

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

示例 1:

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

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一种:暴力解法

思路:

暴力解法比较容易想到。

利用两个循环进行遍历每个元素,外层循环锁定第一个元素,内层循环锁定第二个元素,然后这两个元素去判断之和是不是为目标数,是就返回对应的下标,不是的话就返回就继续循环。

代码:

public int[] twoSum(int[] nums, int target) {
        int [] index =new int[2];
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[i]+nums[j]==target){
                    index[0]=i;
                    index[1]=j;
                    return index;
                }
            }
        }
        return index;
    }

第二种:利用Hash表解题

思路:

利用Hash表来解题,将数组放在Hash表中,将值作为key,数组对应下标对应value,用目标数去减第一个数,得到一个剩下得值,然后利用这个值去判断是否存在Hash表中,以此循环。

代码:

Map<Integer, Integer> map = new HashMap();
        for (int i = 0; i < nums.length; ++i) {
            int num = target - nums[i];
            /*判断hash表中是否存在这个key值*/
            if (map.containsKey(num)) {
                return new int[]{map.get(num),i};
            }
            /*将数组的值和下标添加到hash表*/
            map.put(nums[i], i);
        }
        return null;
    }

2、两数相加

date:2021/08/06

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

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

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

示例 1:

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

输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

迭代法

思路:

img

2+5=7 将7放在和链表对应的位置

4+6=10 因为一个节点只可以存一个数,故将个位放在和链表对应的位置,然后十位的1,进到下一个节点

3+4=7+1 =8 因为上一个节点有进位,还得加上进位的1才可以,然后将8放在和链表对应的位置。

我们可以把整个过程抽象成一个公式:

total=val1+val2+carry total 为总和,carry为进位

保存在和链表的值:val3=total%10

下一个节点的进位carry=total/10

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int next1 = 0;//进位
        int total = 0;//总和
        ListNode sum = new ListNode();//和链表
        ListNode cur = sum;//加一个头指针
        while (l1 != null && l2 != null) {//两个链表对其的时候
            total = l1.val + l2.val + next1;
            cur.next = new ListNode(total % 10);//写入和链表的个位
            next1 = total / 10;//保存进位
            l1 = l1.next;//向下移动
            l2 = l2.next;
            cur = cur.next;
        }

        while (l1 != null) {//l2为空了
            total = l1.val + next1;
            cur.next = new ListNode(total % 10);
            next1 = total / 10;
            l1 = l1.next;
            cur = cur.next;
        }

        while (l2 != null) {
            total = l2.val + next1;
            cur.next = new ListNode(total % 10);
            next1 = total / 10;
            l2 = l2.next;
            cur = cur.next;
        }

        if (next1 != 0) {
            cur.next = new ListNode(next1);
        }
        return sum.next;
    }
    }
}

3、无重复字符的最长子串

date:2021/08/11

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

示例 1:

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

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

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

输入: s = “”
输出: 0

提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

暴力遍历解法

date:2021/08/12

思路:先将字符串转化为数组,用两个指针循环遍历数组,先将外层的字符放入hash表中。然后比较元素是否存在于hash表中,如何没有就就加入到哈希表,如何存在了就跳出内层循环,进行下一次外层循环。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AcIboS9h-1628767885284)(LeetCode.assets/image-20210812182412253.png)]

hashMap //定义一个散列表
for(i){
    //将第一个元素放进hash表
    for(j){
        判断第j个元素是否在哈希表中
        如果不在就放进hash表
            if(hashMap.containsKey()){
                
            }else{
                如果存在哈希表中,那么我们就需要进行下一次寻找
                 那这一次内循环就结束
                    break;
            }
    }
}





public int lengthOfLongestSubstring(String s) {
        char[] chars = s.toCharArray();
        int maxLen=0;//记录最大长度
        Map child = new HashMap();//将子串放入哈希集合
        if (chars.length!=0){
            maxLen=1;
        }
        for(int i=0;i<chars.length;++i){
            //每次循环将set置空
            child.clear();
            //将i位置的元素放入
            child.put(chars[i],i);
            for(int j=i+1;j<chars.length;++j){
                //判断子串中是否存在该元素
                if(!child.containsKey(chars[j])){//如果不存在
                    //放入哈希表
                    child.put(chars[j],j);
                }else {
                    break;
                }
                if (child.size()>maxLen){//哈希表长度大于最长
                    int len=child.size();
                    maxLen=len;
                }
            }
        }
        return maxLen;
    }

滑动窗口解法

这道题主要用到思路是:滑动窗口

什么是滑动窗口?

其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

 public int lengthOfLongestSubstring1(String s) {
        char[] chars = s.toCharArray();
        Map<Character,Integer> child = new HashMap();//将子串放入哈希集合
        int maxLen=0;//记录最大长度
        int front=0;//前指针
        int next=1;//后指针
        int value=0;//记录元素位置
        if(chars.length!=0){
            child.put(chars[front],front);
            maxLen=1;
        }
        while(next<chars.length){
            if(child.containsKey(chars[next])){//如果相等
                child.remove(chars[value++]);//移除元素
                front=value+1;//从这里开始循环b
               // next=front+1;
               // value++;
            }else {//没有相同就放进去
                child.put(chars[next],next);
                next++;//数组下标下移
            }
            if(child.size()>maxLen){
                maxLen=child.size();
            }
        }
        return maxLen;
    }
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陈斌-cb

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

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

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

打赏作者

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

抵扣说明:

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

余额充值