[动态规划][链表]不同路径Ⅱ、反转链表
题目:
不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明:m 和 n 的值均不超过 100。
问总共有多少条不同的路径?
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
题解:该题目标注为中等难度,有点言过其实。
典型动态规划的题,其状态转移方程dp[i][j]=dp[i-1][j]+dp[i][j-1]
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m,vector<int>(n,1));
for(int i=1;i<m;++i){
for(int j=1;j<n;++j){
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
题目二:
翻转链表
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
题解:该题重点在于要注意边界条件,同时要注意题目要求是一次遍历完成,做完该题,我发现其他很多人的做法虽然也做出来但是不符合题目要求。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//链表分为三种情况
// a-->b-->c-->d-->e-->f-->null
//假设 --- ---
// | |
// \|/ \|/
// m n
//边界情况一
// a-->b-->c-->d-->e-->f-->null
// --- ---
// | |
// \|/ \|/
// m n
//边界情况二
// a-->b-->c-->d-->e-->f-->null
// --- ---
// | |
// \|/ \|/
// m n
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(m==n) return head;
ListNode* node=head;
ListNode* subnode=head;
ListNode* pre=nullptr;
ListNode* curr=nullptr;
ListNode* next=nullptr;
ListNode* Flag;
int num=0;
//引入(num+1>n)条件,确保翻转结束节点为最后节点时,更新返回值
while(node!=nullptr||num+1>n){
++num;
if(num<m){
//记录开始反转的上一个节点,以便连接翻转部分链表
if(num+1==m){
subnode=node;
}
node=node->next;
continue;
}
//判断是否完成反转部分
if(num>n){
//开始翻转部分需要直接链接上后续未翻转部分
Flag->next=node;
if(m!=1){ //如果是从收个节点反转,则头结点调整
subnode->next=pre;
}else{
//如果从第一个节点开始翻转,其首节点改变
head=pre;
}
break;
}
curr=node;
next=node->next;
node->next=pre;
pre=curr;
node=next;
//此处记录开始翻转的节点
if(num==m){
Flag=pre;
}
}
return head;
}
};