1.动态规划(DP)
动态规划解题分为4步:
1.划分子问题
2.求子问题的递推关系(递推式、边界)
3.求解子问题(使用DP数组)
4.空间优化
入门题
题解:
子问题:打劫前k个房子时,对于第k个房子,最高金额为max(打劫前k-2个房子的最高金额+打劫第k个房子的金额,打劫前k-1个房子并放弃第k个房子的金额)
class Solution {
public:
int rob(vector<int>& nums) {
int pre2=0;
int pre1=0;
int temp;
for(int x:nums){
temp=pre1;
pre1=max(x+pre2,pre1);
pre2=temp;
}
return pre1;
}
};
2.归并排序(链表排序)
使用bottom-to-up,时间复杂度为O(nlogn),空间复杂度为O(1)
cut:切割链表
merge:合并链表
每次合并,单元的长度为intv(第一轮intv=1,第二轮intv=2,第三轮intv=4...直到intv>=链表长度)
使用额外的结点res,使res->next始终指向head
ListNode* sortList(ListNode* head) {
ListNode res(0);
res.next = head;
ListNode* p = head;
int length = 0;
while (p) {
++length;
p = p->next;
}//求链表长度length
for (int intv = 1; intv < length; intv *=2 ) {
ListNode* cur = res.next;//当前待切割的起点
ListNode* tail = &res;//已合并部分的尾部
while (cur) {
ListNode* left = cur;
ListNode* right = cut(left, intv); //以left为起点切割左边一串
cur = cut(right, intv);//以right为起点切割右边一串
tail->next = merge(left, right);//合并切割出的两段,并连接到尾部
while (tail->next) tail = tail->next;
}
}
return res.next;
}
ListNode* cut(ListNode* head, int n) {
ListNode* p = head;
while (--n&&p) {
p = p->next;
}
if (!p) return nullptr;
ListNode* next = p->next;
p->next = nullptr;
return next;
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode res(0);
ListNode* p = &res;
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
p = l1;
l1 = l1->next;
} else {
p->next = l2;
p = l2;
l2 = l2->next;
}
}
p->next = l1 ? l1 : l2;
return res.next;
}