目录
- 1.合并k个已排序的链表
- 1.题目链接
- 2.算法原理讲解 && 代码实现
- 2.dd爱旋转
- 1.题目链接
- 2.算法原理详解 && 代码详解
- 3.小红取数
- 1.题目链接
- 2.算法原理详解 && 代码实现
1.合并k个已排序的链表
1.题目链接
- 合并k个已排序的链表
2.算法原理讲解 && 代码实现
- 自己的解法:堆 -> 将全部节点丢入堆中
class Solution {typedef pair<int, ListNode*> PIL; public:ListNode* mergeKLists(vector<ListNode*>& lists) {priority_queue<PIL, vector<PIL>, greater<>> heap;for(const auto& list : lists){ListNode* cur = list;while(cur){heap.push({cur->val, cur});cur = cur->next;}}ListNode* newHead = new ListNode(0);ListNode* tail = newHead;while(heap.size()){ListNode* node = heap.top().second;heap.pop();tail->next = node;tail = tail->next;}tail->next = nullptr;tail = newHead->next;delete newHead;return tail;} };
- 优化解法:堆 -> 只存入每个链表的头结点,出堆时,再压入下一个节点
- 对自己的版本进行了时间上和空间上的优化
- 并且对堆排序时的比较方法进行了优化
class Solution {struct CMP{bool operator()(ListNode* l1, ListNode* l2){return l1->val > l2->val;}}; public:ListNode* mergeKLists(vector<ListNode*>& lists) {priority_queue<ListNode*, vector<ListNode*>, CMP> heap;for(auto head : lists){if(head != nullptr){heap.push(head);}}ListNode* newHead = new ListNode(0);ListNode* tail = newHead;while(heap.size()){ListNode* tmp = heap.top();heap.pop();tail = tail->next = tmp;if(tmp->next != nullptr){heap.push(tmp->next);}}tail = newHead->next;delete newHead;return tail;} };
2.dd爱旋转
1.题目链接
- dd爱旋转
2.算法原理详解 && 代码详解
- 解法:模拟 + 优化
- 180° --> 一次行对称 + 一次列对称
- 行列的顺序无所谓
- 如果为偶数次,则无需变换
#include <iostream> #include <vector> using namespace std;int n = 0; vector<vector<int>> matrix;void SwapRol() // 行对称 {for(int i = 0; i < n / 2; i++){for(int j = 0; j < n; j++){swap(matrix[i][j], matrix[n - 1 - i][j]);}} }void SwapCol() // 列对称 {for(int j = 0; j < n / 2; j++){for(int i = 0; i < n; i++){swap(matrix[i][j], matrix[i][n - 1 - j]);}} }int main() {cin >> n;matrix.resize(n, vector<int>(n, 0));for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){cin >> matrix[i][j];}}int q = 0, x = 0;cin >> q;int row = 0, col = 0;while(q--){cin >> x;if(x == 1){row++, col++;}else{row++;}}if(row %= 2){SwapRol();}if(col %= 2){SwapCol();}for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){cout << matrix[i][j] << " ";}cout << endl;}return 0; }
3.小红取数
1.题目链接
- 小红取数
2.算法原理详解 && 代码实现
- 解法:01背包 + 同余(倍数问题可以转换为余数问题)
-
同余定理:
-
状态表示:
dp[i][j]
:从前i
个数中挑选,总和%k
等于j
时,最大和是多少 -
状态转移方程:
-
初始化:
-
返回值:
dp[n][0]
--> 因为k
的倍数的余数为0
#include <iostream> #include <vector> #include <climits> using namespace std;int main() {int n = 0, k = 0;cin >> n >> k;vector<long long> nums(n + 1, 0);for(int i = 1; i <= n ; i++){cin >> nums[i];}vector<vector<long long>> dp(n + 1, vector<long long>(k, LLONG_MIN));dp[0][0] = 0;for(int i = 1; i <= n; i++){for(int j = 0; j < k; j++){dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - nums[i] % k + k) % k] + nums[i]);}}cout << (dp[n][0] <= 0 ? -1 : dp[n][0]) << endl;return 0; }
-