Leetcode 2:两数相加

题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

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

示例

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

代码实现

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { if(l1==NULL) return l2; if(l2==NULL) return l1; ListNode *tmp=new ListNode(-1); ListNode *res=tmp; ListNode *add1=l1; ListNode *add2=l2; int ge=0; int jin=0; while(add1!=NULL || add2!=NULL||jin) { ge=(add1?add1->val:0)+(add2?add2->val:0)+jin; jin=ge/10; ge=ge%10; ListNode *newnode = new ListNode(ge); tmp->next=newnode; tmp=tmp->next; if(add1) add1=add1->next; if(add2) add2=add2->next; } return res->next; }

执行用时&内存消耗

复杂度分析

Leetcode 3:无重复字符的最长子串

题目描述

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

示例

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

代码实现

int lengthOfLongestSubstring(string s) {        int len = s.size();        vector<int> a(256,-1);        int maxlen = 0;        int l = -1;        for(int i=0; i<len; i++){            l = max(l,a[s[i]]);            a[s[i]] = i;            maxlen = max(maxlen,i-l);        }               return maxlen;     }

执行用时&占用空间

复杂度分析

Leetcode 72:编辑距离

题目描述

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  1. 插入一个字符
  2. 删除一个字符
  3. 替换一个字符

示例

输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

解题思路

代码实现

int min3(int a, int b, int c){    return (a < b) ? (a < c ? a : c) : (b < c ? b : c);}int minDistance(string word1, string word2) {    int strlen1 = word1.size();    int strlen2 = word2.size();    vector<vector<int>>dp(strlen1 + 1, vector<int>(strlen2 + 1, 0));    for (int i = 1; i <= strlen1; i++)        dp[i][0] = i;    for (int i = 1; i <= strlen2; i++)        dp[0][i] = i;    for (int i = 1; i <= strlen1; i++)    {        for (int j = 1; j <= strlen2; j++)        {            int diff;            if (word1[i - 1] == word2[j - 1])                diff = 0;            else                diff = 1;            dp[i][j] = min3(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + diff);        }    }    return dp[strlen1][strlen2];}

复杂度

时间复杂度:算法有两个for循环,一个双重for循环。如果两个字符串分别是m和n,前两个for循环时间复杂度为O(n)和O(m)。双重for循环时间复杂度为O(n * m),所以总时间复杂度是O(n * m)。

空间复杂度:O(n * m)

复杂度分析

Leetcode 75:颜色分类

题目描述

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

示例

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

解题思路

此题是一个荷兰国旗问题,曾经在博客和公众号中都推送过这个问题的解决方案。所谓荷兰国旗问题,或者说黑猫白猫灰猫问题,其实都是一样的,就是说有三类数据乱序排列,然后要求用O(N)的时间复杂度,O(1)的空间复杂度使其有序。因其类似于荷兰国旗,所以被称为荷兰国旗问题(德国、法国在这里表示不服~)。

具体思路如下:

排序方法:设置start/end/current三个指针,分别指向开头、开头、结尾。在current<=end的背景下,然后开始判断current的值:

  1. 若current==0,因为0要排在前面,所以则将start指向的值和current的值交换,然后start++,current++;
  2. 若current==1,因为1是排在中间,所以current++,start不变;
  3. 若current==2,则将current和end的元素交换,将end–,但是current不变,如果current后移1位,那么current这一位就无法判断了。

代码实现

void sortColorsl(vector<int> &nums){ int len = nums.size(); int start = 0, current = 0, end = len - 1; //在current<=end的背景下,然后开始判断current的值 while (current <= end) { //1.若current==0,则将start指向的值和current的值交换,然后start++,current++; if (nums[current] == 0) { swap(nums[current], nums[start]); ++current; ++start; } //3.若current==2,则将current和end的元素交换,将end--,但是current不变。 else if (nums[current] == 2) { swap(nums[current], nums[end]); --end; } //2.若current==1,则current++,start不变; else if (nums[current] == 1) { ++current; } }}

复杂度

时间复杂度:O(n)

复杂度分析

Leetcode 76:最小覆盖子串

题目描述

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

如果 S 中不存这样的子串,则返回空字符串 “”。如果 S 中存在这样的子串,我们保证它是唯一的答案。

示例

输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”

解题思路

其实这个题的题目的英文Minimum winow substring给了我们一个答案,就是用窗来解决,但是中文名称却掩盖了这一点。

简单来说思路就是这样:设置一个左指针left,设置一个有指针right,然后不断移动右指针right,然后可以寻找到一个覆盖面最广的子串(最长覆盖子串),当然如果right移动到最后一个字母都没有找到覆盖子串的话,就是找不到了。完成这一步之后,开始移动left,这个时候寻找最小覆盖子串。

代码实现

string minWindow(string s, string t){    int count[256] = { 0 };    for (auto c : t)++count;//统计t中每个字符出现的次数    int len = 0, minlen = s.size();//minlen最大为s的长度    string res;    for (int l = 0, r = 0; r < s.size(); ++r) {        if (--count[s[r]] >= 0)++len;        //上面这句话的意思是:不断移动窗口的right,同时若在s中发现t中有的字符,则len++        //直到len加到和t相同,也就是在s中找到了一个字符串        //下面就是找最优字符串了        while (len == t.size()) {            if (r - l + 1 <= minlen) {                minlen = r - l + 1;                res = s.substr(l, minlen);            }            if (++count[s[l++]] > 0)--len;        }                }    return res;}

复杂度

时间复杂度O(m* n),m和n分别为s和t的长度。

复杂度分析