LeetCode刷题 day07

一.两数相加(链表)

1.题目要求

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:
在这里插入图片描述

2.题目解析

在这之前,我们知道十进制的运算方式,逢10进1,所以这里设置进制数carry。(因为是相加,carry只会是0或1。)

  • 两个链表对应节点值为n1和n2,sum=n1+n2+carry,carry初始化为0,因为是逆序,进制的方向也是逆序,所以是从左向右进1。因为大于10要进制,所以保留下来的数为sn=sum%10,进制数carry=sum/10
  • 这里以2->4->3和5->6->4为例:
    2+5=7,
    4+6=10,逢10进制,所以sn=10%10=0,carry=10/10=1。
    3+4+carry(目前为1)=8。
  • 注意:如果最后还有进制1,在最后添加1这个数字结点。
  • 最后返回头结点即可

3.具体代码

其中,我添加了注释,方便理解:

/**
 * 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; }
 * }
 */
   public ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
        // 创建头结点和尾结点指针
        ListNode head = null, tail = null;
        int carry = 0; // 进位值初始化为0

        while (l1 != null || l2 != null) {    // 遍历两个链表节点
            int n1 = l1 != null ? l1.val : 0; // 获取链表l1当前节点的值,如果为空则为0
            int n2 = l2 != null ? l2.val : 0; // 获取链表l2当前节点的值,如果为空则为0
            int sum = n1 + n2 + carry;        // 计算当前节点值的和以及进位值

            if (head == null) {            // 如果当前节点是结果链表的头结点
            // 创建新节点,并将其同时赋值给head和tail
                head = tail = new ListNode(sum % 10); 
            } else {
                tail.next = new ListNode(sum % 10); // 创建新节点
                tail = tail.next; // 更新tail为新节点,保持链表尾部正确
            }

            carry = sum / 10; // 更新进位值

            if (l1 != null) {
                l1 = l1.next; // 遍历到下一个l1的节点
            }

            if (l2 != null) {
                l2 = l2.next; // 遍历到下一个l2的节点
            }
        }

        if (carry > 0) { // 如果最后一次相加有进位
            tail.next = new ListNode(carry); // 创建新节点,将进位值连接到结果链表的尾部
        }

        return head; // 返回结果链表的头结点
    }

二.无重复字符的最长子串

1.题目要求

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

示例 :

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

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

2.解析

  • 首先想到的是暴力算法,双循环,但是时间复杂度直接来到了O(n^2)
  • 这里推荐两种方法:双指针和map映射表,其中异曲同工之妙都是滑动窗口。
  • 什么是滑动窗口呢?
    第一次添加字符到集合中,依次添加,并记录长度。当遇到重复数字时,将起点重新设置到排除重复数字的后面。
    在这里插入图片描述

3.双指针代码

   public int lengthOfLongestSubstring3(String s) {
            int n = s.length();
            int maxLength = 0;
            int i = 0, j = 0;
            Set<Character> set = new LinkedHashSet<>(); // 用于存储窗口中的字符集合

            while (i < n && j < n) {
                if (!set.contains(s.charAt(j))) { // 如果窗口中不存在 s[j] 字符
                    set.add(s.charAt(j++)); // 将 s[j] 加入集合并同时向右移动 j 指针
                    maxLength = Math.max(maxLength, j - i); // 更新最长长度
                } else {
                    set.remove(s.charAt(i++)); // 将 s[i] 从集合中移除并同时向右移动 i 指针
                }
            }

            return maxLength;
        }

4.map代码

   public  static int lengthOfLongestSubstring1(String s) {
       int cast=0;    //初始化最长长度
       int n=s.length();
        //map映射表
        Map<Character,Integer> map=new HashMap<>();
        //长度记录的起点和终点
        for(int end=0,start=0;end<n;end++){
            //从头开始获取字符串的字符
         char solo=s.charAt(end);
         //如果集合中已经含有该字符的话,窗口要滑动
         if(map.containsKey(solo)){
             start=Math.max(map.get(solo),start);
         }
         //更新map和长度cast
            cast=Math.max(cast,end-+1);
         //其中end+1表示字符在字符串中的位置+1
         map.put(s.charAt(end),end+1);
        }
        return cast;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱笑的蓝孩子~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值