目录
Day24-学习内容:
1.剑指Offer
面试题35:复杂链表的复制
面试题:跳台阶
面试题:变态跳台阶
2.Leetcode
例1:加油站索引
例2:三角形最短路径和
例3:不同子序列树
1.剑指Offer
面试题35:复杂链表的复制
题目描述:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
思路:分解、图形化、理清思路,时间复杂度O(n),空间复杂度O(1).
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { CloneNode(pHead); CloneRandomNode(pHead); return ReconnectNode(pHead); } void CloneNode(RandomListNode* pHead){ RandomListNode* pNode=pHead; while(pNode!=nullptr){ RandomListNode* pCloned=new RandomListNode(pNode->label); //pCloned->label=pNode->label; pCloned->random=nullptr; pCloned->next=pNode->next; pNode->next=pCloned; pNode=pCloned->next; } } void CloneRandomNode(RandomListNode* pHead){ RandomListNode* pNode=pHead; while(pNode!=nullptr){ RandomListNode* pCloned=pNode->next; if(pNode->random!=nullptr){ pCloned->random=pNode->random->next; } pNode=pCloned->next; } } RandomListNode* ReconnectNode(RandomListNode* pHead){ RandomListNode* pNode=pHead; RandomListNode* pClonedHead=nullptr; RandomListNode* pCloned=nullptr; if(pNode!=nullptr){ pClonedHead=pCloned=pNode->next; pNode->next=pCloned->next; pNode=pNode->next; } while(pNode!=nullptr){ pCloned->next=pNode->next; pCloned=pCloned->next; pNode->next=pCloned->next; pNode=pNode->next; } return pClonedHead; } };
面试题:跳台阶
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:对于本题,前提只有一次1阶或者2阶的跳法。
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由ab假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
e.可以发现最终得出的是一个斐波那契数列.
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Solution { public: int jumpFloor(int number) { if(number<=0){ return -1; } else if(number==1){ return 1; } else if(number==2){ return 2; } else{ return jumpFloor(number-1)+jumpFloor(number-2); } } };
面试题:变态跳台阶
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:关于本题,前提是n个台阶会有一次n阶的跳法。分析如下:
f(1) = 1
f(2) = f(2-1) + f(2-2) //f(2-2) 表示2阶一次跳2阶的次数。
f(3) = f(3-1) + f(3-2) + f(3-3)
...
f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n)
说明:
1)这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。
2)n = 1时,只有1种跳法,f(1) = 1
3) n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2)
4) n = 3时,会有三种跳得方式,1阶、2阶、3阶,
那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)
因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)
5) n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:
f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)
6) 由以上已经是一种结论,但是为了简单,我们可以继续简化:
f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)
可以得出:
f(n) = 2*f(n-1)
7) 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:
| 1 ,(n=0 )
f(n) = | 1 ,(n=1 )
| 2*f(n-1),(n>=2)
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution { public: int jumpFloorII(int number) { if(number==0){ return -1; } else if(number==1){ return 1; } else{ return 2*jumpFloorII(number-1); } } };
2.Leetcode
例1:加油站索引
题目描述:
There are N gas stations along a circular route, where the amount of gas at station i isgas[i].
You have a car with an unlimited gas tank and it costscost[i]of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas station's index if you can travel around the circuit once, otherwise return -1.
Note:
The solution is guaranteed to be unique.
思路:
从start出发, 如果油量足够, 可以一直向后走 end++; 油量不够的时候, start向后退 最终 start == end的时候,如果有解一定是当前 start所在位置。
考察点:贪心算法
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { int start=gas.size()-1; int end=0; int sum=gas[start]-cost[start]; while(start>end){ if(sum>=0){ sum+=gas[end]-cost[end]; ++end; } else{ --start; sum+=gas[start]-cost[start]; } } return sum>=0?start:-1; } };
解析:
贪心算法是指:在每一步求解的步骤中,它要求“贪婪”的选择最佳操作,并希望通过一系列的最优选择,能够产生一个问题的(全局的)最优解。
贪心算法每一步必须满足一下条件:
1、可行的:即它必须满足问题的约束。
2、局部最优:他是当前步骤中所有可行选择中最佳的局部选择。
3、不可取消:即选择一旦做出,在算法的后面步骤就不可改变了。
https://www.cnblogs.com/xsyfl/p/6938642.html
例2:三角形最短路径和
题目描述:
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
1
2
3
4
5
6
7[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is11(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
考察点:动态规划
思路:
// 给定一个三角形,找出从顶到底的最小路径和,每一步可以从上一行移动到下一行相邻的数字
// [
// [2], [2],
// [3,4], [3, 4], [2],
// [6,5,7], ==> [7, 6, 10] ==> [9, 10] ==> [11]
// [4,1,8,3]
// ]
* 自底向上 dp: 不需要额外的空间
* dp[i][j] = min(dp[i+1][j], dp[i+1][j+1]) + triangle[i][j]
* dp[i][j]: 表示到达 (i, j)最小路径的总和
代码:
1
2
3
4
5
6
7
8
9
10
11
12class Solution { public: //从下往上找,不使用额外空间,缺点是修改了输入 int minimumTotal(vector<vector<int> > &triangle) { for(int i=triangle.size()-2;i>=0;i--){ for(int j=0;j<triangle[i].size();j++){ triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]); } } return triangle[0][0]; } };
例3:不同子序列树
题目描述:
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie,"ACE"is a subsequence of"ABCDE"while"AEC"is not).
Here is an example:
S ="rabbbit", T ="rabbit"
Return3.
思路:
//array(i , j ) 表示T[0,j] 在S[0,i] 中的匹配个数
//如果不使用S[i] , 那么f(i , j) = f(i-1 , j)
//如果使用了S[i] , 那么一定有 S[i] == T[j] , f( i , j ) = f(i -1 , j -1 )
//所以当S[i]==T[j]时,有array( i , j ) = array( i -1 , j ) + array(i - 1 , j - 1);
//当S[i]!=T[j]时,有array( i , j ) = array( i -1 , j );
//在使用中不难发现该dp二维数组可以降维,注意改变数组元素值时由后往前
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution { public: int numDistinct(string S, string T) { int len=T.size(); vector<int> array(len+1); array[0]=1; for(int i=1;i<S.size()+1;i++){ for(int j=min(i,len);j>0;j--){ if(S[i-1]==T[j-1]){ array[j]=array[j]+array[j-1]; } } } return array[len]; } };
最后
以上就是追寻保温杯最近收集整理的关于编程之旅-Day24目录的全部内容,更多相关编程之旅-Day24目录内容请搜索靠谱客的其他文章。
发表评论 取消回复