
大部分为抄答案,看解析,且跳过困难的题目,希望能学到点东西
-
有效的字母异位词 还是两个哈希表,不过我把它弄成了一个
-
同构字符串 两个哈希表,还不错啦;
-
对称二叉树
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */bool compare(struct TreeNode* left, struct TreeNode* right) { if ((left == NULL && right != NULL) || (left != NULL && right == NULL)) { /* 单个节点为空,匹配失败 */ return false; } else if (left == NULL && right == NULL) { /* 都为空,匹配成功 */ return true; } else if (left->val != right->val) { /* 都不为空,节点值不相同,匹配失败 */ return false; } /* 运行到此表示当前节点不为空,且节点值相等,开始递归 */ bool outside = compare(left->left, right->right); bool inside = compare(left->right, right->left); /* 返回递归结果 */ return outside && inside;}
bool isSymmetric(struct TreeNode* root){ /* 根节点为空,则对称 */ if (root == NULL) { return true; } /* 递归判断 */ return compare(root->left, root->right);}
-
相同的树 蛮顺利的
-
合并两个有序链表
大佬递归确实强
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */
//根节点写的不太顺利,但做出来了struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) { struct ListNode *use; // struct ListNode root; struct ListNode* root = (struct ListNode*)malloc(sizeof(struct ListNode)); // root = list2; // use = root->next; root->next = NULL; use = root; int temp = 0; while (list1 || list2) { if (!list1) { // list1 null use->next = list2; list2 = list2->next; use = use->next; } else if (!list2) { // list2 null use->next = list1; list1 = list1->next; use = use->next; } else { // compare if (list1->val < list2->val) { use->next = list1; list1 = list1->next; use = use->next; } else { use->next = list2; list2 = list2->next; use = use->next; } } } return root->next;}
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) { if (list1 == NULL) { return list2; } if (list2 == NULL) { return list1; }
struct ListNode* mergedList;
if (list1->val <= list2->val) { mergedList = list1; mergedList->next = mergeTwoLists(list1->next, list2); } else { mergedList = list2; mergedList->next = mergeTwoLists(list1, list2->next); }
return mergedList;}
作者:tt-1103链接:https://leetcode.cn/problems/merge-two-sorted-lists/solutions/2512813/he-bing-you-xu-lian-biao-by-tt-1103-74r9/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 两数相加
// 链表递归 https://leetcode.cn/problems/add-two-numbers/description/struct ListNode *helper(struct ListNode *l1, struct ListNode *l2, int carry){ if (l1 == NULL && l2 == NULL && carry == 0) { return NULL; }
int sum = carry; if (l1 != NULL) { sum += l1->val; l1 = l1->next; } if (l2 != NULL) { sum += l2->val; l2 = l2->next; }
struct ListNode *l = malloc(sizeof(struct ListNode)); l->val = sum % 10; l->next = helper(l1, l2, sum / 10);
return l;}
struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2){ return helper(l1, l2, 0);}
20. 有效的括号 大佬的答案
bool isValid(char* s) { char mp[128] = {}; mp[')'] = '('; mp[']'] = '['; mp['}'] = '{';
int top = 0; // 直接把 s 当作栈 for (int i = 0; s[i]; i++) { char c = s[i]; if (mp[c] == 0) { // c 是左括号 s[top++] = c; // 入栈 } else if (top == 0 || s[--top] != mp[c]) { // c 是右括号 return false; // 没有左括号,或者左括号类型不对 } } return top == 0; // 所有左括号必须匹配完毕}
能猜到双指针我就很知足了,
难点在原地
看答案,找规律,转置+翻转,完成
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
int temp;
// 转置
for (int i = 0; i < matrixSize; i++) {
for (int j = i + 1; j < matrixSize; j++) {
temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 翻转
for (int i = 0; i < matrixSize; i++) { // 行
for (int j = 0; j < matrixSize/2; j++) { //列
temp = matrix[i][j];
matrix[i][j] = matrix[i][matrixSize-j-1];
matrix[i][matrixSize-j-1] = temp;
}
}
}
238. 除自身以外数组的乘积(做出了,但耗时,再做)
380. O(1) 时间插入、删除和获取随机元素(再看看吧) 45. 跳跃游戏 II(再做)
55. 跳跃游戏(想耍小聪明降低运算时间,但是各种漏洞)
121. 买卖股票的最佳时机(做了,耗时,脑子不够灵活再做)
189. 轮转数组 (做出来了,比我预期的好得多)
169. 多数元素 (做了,但耗时再做)
80. 删除有序数组中的重复项 II
给你一个有序数组 nums
,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
int removeDuplicates(int* nums, int numsSize) {
if (numsSize <= 2) {
return numsSize;
}
int slow = 2, fast = 2;
while (fast < numsSize) {
if (nums[slow - 2] != nums[fast]) {
nums[slow] = nums[fast];
++slow;
}
++fast;
}
return slow;
}
26. 删除有序数组中的重复项
双指针问题做的越来越舒服了 还不错,很快做完了;
27. 移除元素 (work 1.5)
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2
, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,3,0,4]
解释:函数应该返回新的长度 5
, 并且 nums 中的前五个元素为 0
, 1
, 3
, 0
, 4
。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
88. 合并两个有序数组 (work 1)
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0 输出:[1] 解释:需要合并 [1] 和 [] 。 合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1 输出:[1] 解释:需要合并的数组是 [] 和 [1] 。 合并结果是 [1] 。 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
53. 最大子数组和
coolBoy 我觉得这道题目的思想是: 走完这一生如果我和你在一起会变得更好,那我们就在一起,否则我就丢下你。我回顾我最光辉的时刻就是和不同人在一起,变得更好的最长连续时刻
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
进阶:如果你已经实现复杂度为 O(n)
的解法,尝试使用更为精妙的 分治法 求解。
15. 三数之和
复制粘贴
25. K 个一组翻转链表
复制粘贴
215. 数组中的第K个最大元素
复制粘贴
LRU 缓存机制
提交记录
是先去b站看了解析视频然后自己写的,很多cpp的内容还是不熟悉,要继续。
状态 | 日期 | 语言 | 时间 | 空间 | 优化 |
---|---|---|---|---|---|
通过 | 2023.10.10 | C++ | 372 ms | 161.7 MB | 官方题解 |
通过 | 2023.10.10 | C++ | 372 ms | 161.4 MB | ai 优化 |
通过 | 2023.10.10 | C++ | 476 ms | 170.7 MB | |
通过 | 2023.10.10 | C++ | 488 ms | 170.8 MB | |
超出时间限制 | 2023.10.10 | C++ | N/A | N/A | |
超出时间限制 | 2023.10.10 | C++ | N/A | N/A | |
执行出错 | 2023.10.09 | C++ | N/A | N/A | |
执行出错 | 2023.10.09 | C++ | N/A | N/A |
自己的最终代码
class LRUCache {public: LRUCache (int capacity) { __cap = capacity; }
int get (int key) { //key = 0; if (hashmap.find (key) == hashmap.end ()){ // 没找到 return -1; } else { // 添加 key_value kv; kv.key = key; kv.value = hashmap [key]->value;
value_list.erase (hashmap [key]); value_list.push_front (kv); hashmap [key] = value_list.begin (); return kv.value; } return key; }
void put (int key, int value) { if (hashmap.find (key) == hashmap.end ()){ // 没找到 // 满了吗?
if (__cap == hashmap.size ()){ hashmap.erase ( value_list.back ().key); value_list.pop_back (); } // 添加 key_value kv; kv.key = key; kv.value = value; value_list.push_front ( kv); hashmap [key] = value_list.begin ();
} else { // 找到了 // 删除并添加到头
value_list.erase (hashmap [key]); // 添加 key_value kv; kv.key = key; kv.value = value; value_list.push_front ( kv); hashmap [key] = value_list.begin ();
} }private: int __cap; struct key_value { int key; int value; bool operator==(const key_value& kv){ return key == kv.key; } }; map<int, list<key_value>::iterator> hashmap; list<key_value> value_list;
};
ai优化
#include <iostream>#include <unordered_map>#include <list>
class LRUCache {public: LRUCache (int capacity) : capacity (capacity) { }
int get (int key) { if (cache_map.find (key) == cache_map.end ()) { return -1; // 未找到 } else { // 将键值对移到链表头部表示最近使用 moveToFront (key); return cache_map [key]->second; } }
void put (int key, int value) { if (cache_map.find (key) == cache_map.end ()) { if (cache_map.size () >= capacity) { // 缓存已满,删除最久未使用的项目 int lru_key = lru_list.back ().first; cache_map.erase (lru_key); lru_list.pop_back (); } // 添加新项目到链表头部 lru_list.push_front (std::make_pair (key, value)); cache_map [key] = lru_list.begin (); } else { // 更新已存在的键值对的值,然后移到链表头部表示最近使用 cache_map [key]->second = value; moveToFront (key); } }
private: int capacity; std::unordered_map<int, std::list<std::pair<int, int>>::iterator> cache_map; std::list<std::pair<int, int>> lru_list;
// 将键值对移到链表头部 void moveToFront (int key) { auto it = cache_map [key]; lru_list.splice (lru_list.begin (), lru_list, it); cache_map [key] = lru_list.begin (); }};
206. 反转链表
看了下提交记录,应该是复制粘贴,主要是cpp不熟,改天重写一遍
这里就记录一下官方答案吧
/ * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */class Solution {public: ListNode* reverseList(ListNode* head) { if (head == NULL || head->next == NULL) { return head; } ListNode* ret = reverseList(head->next); head->next->next = head; head->next = NULL; return ret; }};
3 无重复字符的最长子串
独立编写
代码
int lengthOfLongestSubstring(string s){ string temp; int ftemp = 0; for(int i = s.length(); i > 0; i--) { if (temp.find(s[s.length() - i]) > temp.length()) // 无重复 temp.find(s[s.length() - i]) == -1 但会很大 所以 { // 无重复 temp.push_back(s[s.length() - i]); ftemp = temp.length() > ftemp ? temp.length() : ftemp; } else { // 有重复 i += (temp.length() - temp.find(s[s.length() - i]) - 1); temp.clear(); temp.push_back(s[s.length() - i]); ftemp = temp.length() > ftemp ? temp.length() : ftemp; } } return ftemp;}
使用到的函数
string::find(char c) // 返回c在string中的位置 无则返回string::nposstring::length() // 返回string的长度string::push_back(char c) // 在string的末尾添加cstring::clear() // 清空string
思路
刚开始看错了题
做完去看评论 发现这个题的思路是滑动窗口 然鹅我不知道那是什么东东 只是大概理解字面意思
这道题主要用到思路是:滑动窗口
什么是滑动窗口?
其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!
一直维持这样的队列,找出队列出现最长的长度时候,求出解!
时间复杂度:O(n)O(n)O(n)
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
总结
c++ 很多特性还不会用 要继续学习