Leetcode进阶----学习(一)【两数相加、无重复字符的最长字串】

两数相加

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

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

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

1.此题解决思想比较简单,直接设置一个进位carry,由于链表是按照逆序存储的,计算两数之和就可以直接从首节点开始计算求和,然后每次求得的和需要计算出该位的进位,即新进位carry = sum/10,在这里需要创建一个新链表用来存储求得的和(通过new创建),然后依次计算每一位之和并加到新链表之中,若某个链表达到尾部,则继续计算另一个链表,遍历完之后,观察进位carry是否存在进位,若存在进位则将1加到新链表尾部,最后返回新链表:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummyRoot = new ListNode(0);    //创建新链表存储求和数据
        ListNode* p = dummyRoot;                 //定义指针p指向新链表
        int carry = 0;
        while (l1 || l2)                       //只有同时为空时,才退出
        {
            int x = l1 ? l1->val : 0;            //判断链表l1是否为空,不为空则取出数据
            int y = l2 ? l2->val : 0;           //判断链表l2是否为空,不为空则取出数据
            int sum = x + y + carry;           //计算两数之和
            carry = sum/10;                    //计算新进位
            p->next = new ListNode(sum%10);    //创建新链表中的新节点
            p = p->next;
            if (l1)                            //如果不为空,继续遍历
                l1 = l1->next;                 
            if (l2)
                l2 = l2->next;
        }
        if (carry == 1)                       //判断是否存在进位,存在则把1加到新链表中
            p->next = new ListNode(1);
        return dummyRoot->next;
    }
};

2.该题还有一种变形,即两个数不是按照逆序存在链表中,而是正序,有兴趣可以参考下Grandyang的博客,具体做法有两种,一种是将链表翻转,然后使用上述的方法求和;另一种不采用翻转链表,有点复杂,感兴趣的同学可以自己去了解。。。

无重复字符的最长字串

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

示例 1:

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

示例 2:

输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b",其长度为 1。

示例 3:

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

1.使用set容器存储字符,如果之前未出现则存入set中,如果出现相同字符则从上一个left开始删除,删除到重复字符为止,其中记录下最大子串长度:

具体分析:

若字符串为abbca

首先i=0,存入set,此时set中存有字符a,更新cnt为1

i=1,没有相同,存入set,此时set中存有字符a、b,更新cnt为2

i=2,出现相同字符b,则从上一个left = 0开始删除,删除后set中无元素,此时st.size()为0

删除过后i=2,此时set中没有相同,存入b,st.size()为1,小于之前cnt,不更新

i=3,存入c,此时st.size()为2,不更新

i=4,存入a,此时st.size()为3,更新cnt为3,则此为最大长度,最大字串为bca

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
        int cnt = 0,left = 0,n = s.size();
        unordered_set<char> st;      //保存出现的字符
        int i = 0;
        while (i < n)
        {
            if (!st.count(s[i]))  //未出现相同字符,则将字符插入set中,并更新子串长度为当前最大
            {
                st.insert(s[i++]);   //插入当前字符,下移一位
                cnt = max(cnt, (int)st.size());
            }
            else
                st.erase(s[left++]);    //出现相同字符则从上一个left开始删除,直到重复字符为止
        }
        return cnt;
	}
};

2.使用hashmap来建立字符与其位置之间的联系,具体使用left标记重复字符的位置,根据该left得出最大长度:

具体分析:

若字符串为abbca

根据该思路,首先建立联系

i=0:left为0,字符‘a'位置为1,res长度为1

i=1:left为0,字符’b‘位置为2,res长度为2

i=2:出现重复字符’b',此时更新left的位置,使其指向上一个‘b’出现的位置2,更新新‘b'的位置为3,更新res长度为1

i=3:left为2,字符‘c’位置为4,res长度为2

i=4:left为2,字符’a‘位置更新为5,res长度更新为3

返回3

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int res = 0, left = 0, i = 0, n = s.size();
        unordered_map<char, int> m;     //建立字符与其位置的联系
        for (int i = 0; i < n; ++i) {   //遍历数组,若出现重复字符则更新left的位置,使其指向重复字符
            left = max(left, m[s[i]]);
            m[s[i]] = i + 1;
            res = max(res, i - left + 1);  //根据left计算最大长度
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/83620066
今日推荐