vlambda博客
学习文章列表

[动态规划][链表]不同路径Ⅱ、反转链表

题目:

不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

例如,上图是一个7 x 3 的网格。有多少可能的路径?

说明:m 和 的值均不超过 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; } };