您的位置:首页 > 其它

leetcode算法思想快速一览

2016-10-22 12:48 302 查看
整理了一下思路,想深入了解还得多去写,无奈时间紧迫的情况下抛砖引玉也不失为下策:

1.Two Sum Easy
给出一个数组,找出其中两个和为目标值的坐标。
思路:

[1]排序。
和为目标值,一般的思路是先排序,然后取两点坐标分别从首尾向中间移动。若和为目标值则返回两点坐标。若和大于目标值,右端坐标值-1,反之左端坐标值+1;
[2]因为需要返回坐标值。需要对键值对进行按值排序。以保留原始坐标。

2.Add Two Numbers Medium
有两个反向存储数字的链表,求他们的和。
思路:

[1]这种需要求和,进位频繁的工作选取一个全局变量来存储临时的和。(比如两个数的个位分别是9和8,那么先不必考虑进位,这个全局变量的值就是17,运算完成后,和的个位值为 全局变量%10, 然后执行 全局变量 /= 10,得出全局变量的剩余值。在计算十位的时候要加上这个剩余值。)
[2]这道题主要还顺带考察了链表的用法。
[3]注意while循环自带逻辑判断。这两个链表的长度不一,所以循环结构可以这样写:
while(链表1当前节点不为空且链表2当前节点不为空) ;//两个链表都还有值
while(链表1当前节点不为空); //链表2已空
while(链表2当前节点不为空); //链表1已空
if(全局变量 > 0) //如果全局变量>0 说明有进位操作,还需要加长结果链表

3.Longest Substring Without Repeating Characters Medium
找出一个字符串的最长子串,这个字串满足的条件是不出现重复字符。
思路:

[1]一次循环就搞定,不要多次遍历字符串。
[2]怎样标志一个字符是否出现过。因为字符的数量是有限的,一般256个标志位就能标志基本ASC码的所有字符。
[3]求最长、最大值的思路,是创建一个值用来保存这个“最大值”,每有可能是最大值的值产生的时候,让这个值和原有的最大值进行比较取二者的最大值作为新的最大值。
[4]解题思路。创建一个int类型的数组 charView[256],其中的每个值都初始化成-1。
创建变量 start(目前而言正在判断的字符串的开始坐标) maxlength(得知的最长字符串的长度)
从给出的字符串的第一个字符到最后一个字符逐个遍历。当前坐标为i start初始化为0
如果charView[str[i]] 的值小于0 说明该字符一次都没出现过,start值不变(即当前所计算的字符串还没出现重复字符,继续计算下去) maxlength = max(i-start, maxlength);然后将charView[str[i]]赋值为i
如果charView[str[i]] 的值大于0 说明该字符出现过。那么我就判断这个值是否在start值的左边(start > i),如果在则说明他对我们当前判断的字符串没有影响,我们不必改变start的值,正常maxlength = max(i-start, maxlength)计算,并将charView[str[i]]赋值为i
如果这个值在start值的右边(start < i),那么说明我们当前计算的字符串出现了重复(就是这个str[i]字符)。我们将start值赋值为i,然后继续去遍历。
最后返回maxlength。

4.Median of Two Sorted Arrays Hard
这题看似简单其实很恶啊,大意就是给出两个已经排序好的数组,找出两个数组所有元素中的中位数。
思路:

[1]设数组1的长度为m 数组2的长度为n总数就是m+n 我们就是要找两个数组中第m+n/2大的元素的值。我们设m+n/2为k
[2]如果a1[k/2-1]大于a2[k/2-1],那么a2[0]到a2[k/2-1]的所有值当中都不可能有中值。原因如下。
就算取a2[0]~a2[k/2-1]当中最大的值作为中值a2[k/2-1],那么需要从a1中取出k/2+1个数排在a2[k/2-1]的左边才能凑够k个数,让a2[k/2]成为两数组第k大的元素。然而a1中取出k/2个最小的元素当中已经有比a2[k/2-1]大的元素了,所以并不能凑齐k-1个比a2[k/2]小的数。
[3]上述是理想情况下(k/2-1既小于a1的长度也小于a2的长度)。如果不是,那么就用短的数组的长度代替这个值进行相同的判断。
[4]然后将删除不可能的元素的两个数组重新判断,这回要找的是第 k -(k/2-1)或这 k-短的那个数组长度 大的值。删除元素的数组的长度和首指针都进行更新。

findKth方法写的非常经典。更能看出这道题的解题思路:
1. 保持A是短的那一个数组,B是长的
2. 平分k, 一半在A,一半在B (如果A的长度不足K/2,那就pa就指到最后一个)
3. 如果pa的值 < pb的值,那证明第K个数肯定不会出现在pa之前,递归,把A数组pa之前的砍掉,同理递归砍B数组。
4. 递归到 m == 0 (短的数组用完了) 就返回 B[k - 1], 或者k == 1(找第一个数)就返回min(A第一个数,B第一个数)。

double findKth(int a[], int m , int b[], int n, int k)
{
if(m > n)
return findKth(b,n,a,m,k);

if(m == 0)
return b[k-1];

if(k == 1)
return min(a[0], b[0]);

int pa = min(k/2, m), pb = k-pa;

if(a[pa -1] < b[pb-1])
return findKth(a + pa, m - pa, b, n, k - pa);
else if(a[pa - 1] > b[pb - a])
return findKth(a, m, b + pb, n - pb, k - pb);
else
return a[pa - 1];
return 0;
}

double findMid(int A[], int m, int B[], int n)
{
int total = m + n;
if(total & 0x1)
{
return findKth(A,m,B,n, total/2+1);
}
else
{
return
(findKth(A,m,B,n, total/2) + findKth(A,m,B,n, total/2 + 1)) / 2;
}
}


5.Longest Palindromic Substring Medium
求一个字符串的最长回文子字符串。
(manachar算法解题思路)
[1]明确需求。回文字符串的可能性有两种,一种是形如abcba这种奇数回文字符串,另一种则是adda这种偶数回文字符串。为了统一算法,我们将一种特殊字符穿插在字符串当中构造成:
#a#b#c#b#a# 和 #a#b#b#a# 这样所有的回文字符串就都成了奇数回文字符串
[2]这道题的一般思路是假设每一个字符都是回文字符串的中位字符。那么就是从头遍历到尾。看看满足每个字符作为中位符的回文字符串有多长。
[3]如何去判断一个字符串是否是回文字符串? 我们的判断方式是从中间开始像两端递推。例如str[i],如果str[i-1] == str[i+1]那么 str[i-1,i+1]就是回文字符串,那么就继续判断str[i-2]和str[i+2]...直到相等或者达到数组边界。这个最大差参与maxlength的计算。
[4]如何去动态规划减少遍历的范围? 我们的做法是保留目前所获得的最长的回文字符串的右边界。如果当前所遍历的字符的坐标位置不大于这个右边界,那么他和目前所获得最长回文字符串是按照中值对称的。如果以他的对称所对应的字符为中值所生成的回文字符串没有
超越最长回文字符串的左边界,那么这个字符就可以pass掉了。他和他的对称值一样,都不是最长的。即便到了左边界值,我们也可以用这个差值来进行递推回文字符串的长度初始值。这样就减少了遍历的数量。
[5]我们求出的结果要除去其中的特殊字符,实际长度为(maxlength-1)/2

6.ZigZag Conversion Easy

将一个字符串z字形状的分解成几个字符串

[1]一次遍历
[2]以从一个纵向延伸的开始点为分割点做循环。即纵轴坐标为0,1,2,...rows-1, rows-2,rows-3 ... 2,1 一次循环结束。

string convert(string s, int nRows){

if(nRows == 1) return s;
string res[nRows];
int i = 0, j, gap = nRows-2;
while(i < s.size()){
for(j = 0; i < s.size() && j < nRows; ++j) res[j] += s[i++];
for(j = gap; i < s.size() && j > 0; --j) res[j] += s[i++];
}
string str = "";
for(i = 0; i < nRows; ++i)
str += res[i];

return str;
}


7.Reverse Integer Easy

将一个整数反转

[1]主要考虑反转过程中不要出现整数溢出的情况
[2]对原整数进行 / 10 计算,直到其结果为0

int reverse(int x) {
const int max = 0x7fffffff;  //int最大值
const int min = 0x80000000;  //int最小值
long long sum = 0;

while(x != 0)
{
int temp = x % 10;
sum = sum * 10 + temp;
if (sum > max || sum < min)   //溢出处理
{
sum = sum > 0 ? max : min;
return sum;
}
x /= 10;
}
return sum;
}


8.String to Integer (atoi) Easy

字符串转化成Int类型。

[1]考虑字符串的前部的空格,要去除。从第一个有效字符开始处理

[2]考虑正负

[3]考虑int值越界的情况

[4]考虑出现不是数字的非法字符

int atoi(const char *str) {
long long cur=0;
int num=0,i=0;
int flag1=0,flag2=0;
while(str[i]!='\0' && str[i]==' ') i++;//开头空格舍弃
if(str[i]=='-') flag1++,i++;
else if(str[i]=='+') flag2++,i++;
for(; str[i]!='\0'; i++)
{
if(str[i]>='0' && str[i]<='9')
{
if(flag1==2)
{
cur=cur*10-(str[i]-'0');//这里是减法,因为cur符号是负号了
if(cur<-2147483648) return -2147483648;
}
else if(flag1==1) cur=-str[i]+'0',flag1++;//将负数的符号记录到cur里
else
{
cur=cur*10+(str[i]-'0');
if(cur>2147483647) return 2147483647;
}
}
else break;
}
num=(int)cur;
return num;
}


9.Palindrome Number Easy

判断一个int是否为回文数。

[1]负数pass掉。
[2]个位数全部是回文数。,
[3]只能利用位数标志了 即最高位 while( number != 0) { number /= 10; count ++;}
[4]左边是pow(10,count-1) 右边是pow(10,1),同时取余比较即可

Regular Expression Matching Hard

Container With Most Water Medium

Integer to Roman Medium

Roman to Integer Easy

Longest Common Prefix Easy

3Sum Medium

3Sum Closest Medium

Letter Combinations of a Phone Number Medium

4Sum Medium

Remove Nth Node From End of List Easy

Valid Parentheses Esay
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: