共 172 篇文章
所以数组是非常繁杂的,也很难用几个固定的套路去定义它,只好常刷常新啦
**算法不是拼智商和天赋,算法是一种可以通过科学合理的方式训练出来的能力**
完全自己实现: ```go func reverseWords(s string) string { length := len(s) left, right := 0, length - 1
import "strconv"
for i := 1; i <= n; i++ { pre := 0
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/string/344-reverse-string.md)
错误代码1:
```go func reverse(ch []byte) { left, right := 0, len(ch) - 1
if length < 2 { return false }
```go func reverseString(s []byte) { left, right := 0, len(s) - 1
if m == 0 { return 0 } if n < m { return -1 }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/stack-and-queue/232-implement-queue-using-stacks.md)
for _, v := range nums { freq[v]++ }
dq := make([]int, 0, k) results := make([]int, 0, length - k + 1)
主要思想是利用两个指针(或称“变量索引”)在数据结构(通常为数组、链表或字符串)上进行遍历
它的目标是**快速定位一个目标元素在数组中的位置**,基本前提是数组必须已经排序,否则二分查找无法正确地工作
在一个待排序序列里,元素往往不仅有用来比较大小的“关键字”,还附带其他属性,例如一组学生记录按成绩排序,成绩相同的同学原本在名单中的先后顺序就体现了他们在班级花名册中的位置
换句话说,时间复杂度告诉我们一个算法运行多少步(或基本操作次数)随着问题规模 n 变化的**趋势**
* **连续内存存储**: 数组在内存中占用一块**连续**区域,每个元素的存储位置可以通过起始地址加上偏移量计算得到 * 所以我们不能单独删除数组中的某个元素,只能**覆盖**,也就是**移动其他元素的地址** * **下标**:数组的下标是**从0**开始的 * **固定大小**: 在大多数**静态数组**实现中(如 C 语言的数组、C++ 中的传统数组
它的**基本特性**包括:
需要将 `key` 映射到 `[0, N)` 的整数范围,其中 `N` 是哈希表的桶(bucket)数量
主要类型有:
int main() { std::stack<int> st; // 底层默认是 deque<int> st.push(10); // 压入元素 st.push(20); std::cout << "栈顶元素: " << st.top() << "\n"; // 20 st.pop(); // 弹出 20 std::cout << "弹出后栈顶: " <<
从最底层来看,字符串其实就是**一段有序的字符序列**(在计算机中通常用字节序列或 Unicode 码点序列来表示),并且会以某种方式标明“结束”或“长度”
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int slow = 0; int sum = 0; int results = INT_MAX; //宏 int length = 0;
class Solution { public: int removeDuplicates(vector<int>& nums) { int slow = 0; //没有修改初始值,导致数组索引越界 for (int fast = 0; fast < nums.size(); fast++) //没有修改初始值,导致数组索引越界 { if (nums[fas
class Solution { public: int removeElement(vector<int>& nums, int val) { int slow = 0; //创建慢指针 for (int fast = 0; fast < nums.size(); fast++) { if (nums[fast] != val) //快指针先遍历 { nu
class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0; for (int fast = 0; fast < nums.size(); fast++) { if (nums[fast] != 0) { swap(nums[slow], nums[fast]); //
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int Left = findLeftBoundary(nums, target); int Right = findRightBoundary(nums, target); if (Left =
class Solution { public: int searchInsert(vector<int>& nums, int target) { int left = 0; //和上一题代码基本没有什么大变化 int right = nums.size() - 1; while (left <= right) { //为了防止int越界,先计算左右边界的
class Solution { public: bool isPerfectSquare(int num) { int square = 0; if (num < 2) { square = num; } int left = 1; int right = num / 2; while (left <= right) { int mid = left +
class Solution { public: vector<vector<int>> generateMatrix(int n) { // 初始化一个二维数组,这里是嵌套的,仔细分析即可弄清楚逻辑 // 有 n 行个 vector,每个 vector 有 n 列,每列都初始化为 0 vector<vector<int>> matrix(n, vector
class Solution { public: int mySqrt(int x) { if (x < 2) //此时无论什么数都会直接返回1 { return x; } int left = 1; //防止出现0在分母 int right = x / 2; //提前缩小范围,提升效率 int result = 0; while (left <= righ
class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; //通过vector自带的size函数得到数组终点位置 while(left <= right) { // (right - left)
class Solution { public: vector<int> sortedSquares(vector<int>& nums) { int i = 0; while (i < nums.size()) { nums[i] = nums[i] * nums[i]; //溢出越界了 } int right = 0, left = 1; while (
这道题主要是对**二分查找**概念的检验,以及如何在 cpp 中实现二分查找算法,通过将基本想法转化一下可得下面的细分步骤: - 创建 left、right 变量用于记录数组起始和结束位置 * left 初始为 0 * right 初始为数组长度减一 - 利用 while 循环,仅当 **left <= right** 时才进入 * 这里考虑使用左闭右闭区间
func backtrack(s string, results *[][]string, path []string, start int) { if start == len(s) { temp := make([]string, len(path)) copy(temp, path) *results = append(*results, temp)
mapping := map[byte]string{ '2': "abc", '3': "def", '4': "ghi", '5': "jkl", '6': "mno", '7': "pqrs", '8': "tuv", '9': "wxyz", }
return results }
```
func combinationSum(candidates []int, target int) [][]int { sort.Ints(candidates)
func combinationSum2(candidates []int, target int) [][]int { sort.Ints(candidates)
func backtrack(nums, path []int, res *[][]int, used []bool) { if len(path) == len(nums) { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp) }
func permuteUnique(nums []int) [][]int { sort.Ints(nums) var res [][]int var path []int used := make([]bool, len(nums)) backtrack(nums, path, &res, used) return res }
func backtrack(nums, path []int, res *[][]int, start int) { if len(path) >= 2 { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp) }
dp := make([]bool, cap + 1) dp[0] = true for _, w := range stones { if w > cap { continue }
func backtrack(nums, path []int, res *[][]int, start int) { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp)
func subsetsWithDup(nums []int) [][]int { var res [][]int var path []int sort.Ints(nums) backtrack(nums, path, &res, 0) return res }
func restoreIpAddresses(s string) []string { var results []string var path []string backtrack(&results, path, 0, s) return results }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/backtracking/77-combinations.md)
return isMirror(root.Left, root.Right) }
var results [][]int queue := []*TreeNode{root} // 由于传入的 root 就是指针类型,这里也要用指针类型
queue := []*TreeNode{root} depth := 0
idxMap := make(map[int]int, n) for i, v := range inorder { idxMap[v] = i }
var results [][]int queue := []*TreeNode{root}
func build(nums []int, l, r int) *TreeNode { if l > r { return nil }
func checkHeight(node *TreeNode) int { if node == nil { return 0 }
queue := []*TreeNode{root} depth := 0 levels := 0
remaining := targetSum - root.Val
func connect(root *Node) *Node { if root == nil { return nil }
return results } ```
var results []int results = append(results, postorderTraversal(root.Left)...) results = append(results, postorderTraversal(root.Right)...) results = append(results, root.Val)
var results []int queue := []*TreeNode{root}
count := 0 queue := []*TreeNode{root}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { for root != nil { if p.Val < root.Val && q.Val < root.Val { root = root.Left } else if p.Val > root.Val && q.Val > root.
l := lowestCommonAncestor(root.Left, p, q) r := lowestCommonAncestor(root.Right, p, q)
func (s *myStack) Push(val int) { s.data = append(s.data, val) }
var sum int
func levelOrder(root *Node) [][]int { if root == nil { return nil }
if key < root.Val { root.Left = deleteNode(root.Left, key) return root } if key > root.Val { root.Right = deleteNode(root.Right, key) return root }
func bfs(node *TreeNode, arr *[]int) { if node == nil { return }
var v int queue := []*TreeNode{root}
import "math"
if root2 == nil { return root1 }
var results []float64 queue := []*TreeNode{root}
maxIdx := 0 for i, _ := range nums { if nums[maxIdx] < nums[i] { maxIdx = i } }
if root.Val < low { return trimBST(root.Right, low, high) } if root.Val > high { return trimBST(root.Left, low, high) }
switch { case root.Val == val: return root case root.Val > val : return searchBST(root.Left, val) default: return searchBST(root.Right, val) } } ```
if root.Val > val { root.Left = insertIntoBST(root.Left, val) } else { root.Right = insertIntoBST(root.Right, val) }
var results []int results = append(results, inorderTraversal(root.Left)...) results = append(results, root.Val) results = append(results, inorderTraversal(root.Right)...)
var prev *TreeNode
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/binary-tree/144-binary-tree-preorder-traversal.md)
queue := []*TreeNode{root}
func (q *myQueue) Push(v int) { q.data = append(q.data, v) }
for i := 0; i < len(s); i++ { for j := m; j >= 1; j-- { if s[i] == t[j - 1] { dp[j] += dp[j - 1] } } }
for i := 1; i < len(prices); i++ { if profit < prices[i] - minPrice { profit = prices[i] - minPrice }
for i := 1; i < len(prices); i++ { preCash, preHold := cash, hold cash = max(preCash, preHold + prices[i]) hold = max(preHold, preCash - prices[i]) }
buy1, sell1 := -prices[0], 0 buy2, sell2 := -prices[0], 0
for i := 1; i <= n; i++ { for _, w := range wordDict { lw := len(w) if i >= lw && dp[i - lw] && s[i - lw : i] == w { dp[i] = true } } }
if k >= n / 2 { ans := 0 for i := 1; i < n; i++{ diff := prices[i] - prices[i - 1] if diff > 0 { ans += diff } } return ans }
return pre1 } ```
a, b := r(nums[1 :]), r(nums[: n - 1]) if a > b { return a } return b }
for i := 1; i <= n; i++ { for j := 1; j * j <= i; j++ { if dp[i] > dp[i - j * j] + 1 { dp[i] = dp[i - j * j] + 1 } } }
dp, ans := make([]int, n), 0
hold, sold, rest := -prices[0], -prices[0], 0
for _, c := range coins { for j := c; j <= amount; j++ { if dp[j] > dp[j - c] + 1 { dp[j] = dp[j - c] + 1 } } }
func dfs(node *TreeNode) (notTake, take int) { if node == nil { return 0, 0 }
for i := 2; i <= n; i++ { max := 0 for j := 1; j < i; j++ { if max < j * (i - j) { max = j * (i - j) } if max < j * dp[i - j] { max = j * dp[i - j] } } dp[i] = max }
for j := 1; j <= target; j++ { for _, n := range nums { if j >= n { dp[j] += dp[j - n] } } }
return i == len(s) } ```
dp := make([]bool, target + 1) dp[0] = true
for _, s := range strs { zeros, ones := 0, 0 for _, ch := range s{ if ch == '0' { zeros++ } else { ones++ } }
if (target + s) % 2 != 0 || abs(target) > s { return 0 } p := (target + s) / 2 dp := make([]int, p + 1) dp[0] = 1
a, b := 0, 1 for i := 2; i <= n; i++ { a, b = b, a + b } return b } ```
for _, c := range coins { for j := c; j <= amount; j++{ dp[j] += dp[j - c] } }
if currSum > maxSum { maxSum = currSum } } return maxSum } ```
for i := 1; i < m; i++ { for j := 1; j < n; j++ { dp[i][j] = dp[i - 1][j] + dp[i][j - 1] } }
for i := 1; i < m; i++ { if obstacleGrid[i][0] == 0 && dp[i - 1][0] == 1 { dp[i][0] = 1 } } for j := 1; j < n; j++ { if obstacleGrid[0][j] == 0 && dp[0][j - 1] == 1{ dp[0][j] = 1 }
for i := 0; i < n; i++ { t[i] = s[n - 1 - i] }
return ans } ```
a, b := 1, 2 for i := 3; i <= n; i++ { a, b = b, a+ b }
cash, hold := 0, -prices[0] for i := 1; i < n; i++{ newCash, newHold := cash, hold
for i := 1; i <= n; i++ { for j := m; j >= 1; j-- { if nums1[i - 1] == nums2[j - 1] { dp[j] = dp[j - 1] + 1
// 空串 -> word2[:j]:插 j 次 for j := 0; j <= m; j++ { dp[j] = j }
for i := 2; i < n; i++{ a, b = b, min(a, b) + cost[i] } return min(a, b) }
for i := 2; i <= n; i++ { total := 0 for j := 1; j <= i; j++ { total += dp[j - 1] * dp[i - j] } dp[i] = total }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/dynamic-programming/509-fibonacci-number.md)
func largestSumAfterKNegations(nums []int, k int) int { sort.Ints(nums) for i := 0; i < len(nums) && nums[i] < 0 && k > 0; i++ { nums[i] = -nums[i] k-- } sort.Ints(nums) sum := 0 i
return earn } ```
for i := 0; i < len(gas); i++ { gSum += gas[i] cSum += cost[i]
sum, right := 0, 1 for i := n - 1; i >= 0; i-- { if i < n - 1 && ratings[i] > ratings[i + 1] { right++ } else { right = 1 }
count, prediff := 1, 0 for i := 1; i < len(nums); i++ { diff := nums[i] - nums[i - 1] if (diff > 0 && prediff <= 0) || (diff < 0 && prediff >= 0) { count++ prediff = diff } }
func reconstructQueue(people [][]int) [][]int { sort.Slice(people, func(i, j int) bool { if people[i][0] != people[j][0] { return people[i][0] > people[j][0] } return people[i][1]
func eraseOverlapIntervals(intervals [][]int) int { if len(intervals) == 0 { return 0 }
end, f, count := 0, 0, 0 for i, v := range nums { if f < i + v { f = i + v }
func findMinArrowShots(points [][]int) int { if len(points) == 0 { return 0 }
func findContentChildren(g []int, s []int) int { sort.Ints(g) sort.Ints(s)
func merge(intervals [][]int) [][]int { if len(intervals) == 1 { return intervals }
func monotoneIncreasingDigits(n int) int { s := strconv.Itoa(n) digits := []byte(s) mark := len(digits) for i := len(digits) - 1; i > 0; i-- { if digits[i] < digits[i - 1] { digits
res, start, end := make([]int, 0), 0, 0 for i := 0; i < len(s); i++ { if last[s[i] - 'a'] > end { end = last[s[i] - 'a'] } if i == end { res = append(res, end - start + 1) start =
for _, v := range bills { switch v { case 5: five++ case 10: if five == 0 { return false } five-- ten++ case 20: if ten > 0 && five > 0 { ten-- five-- } else if five > 2 { five -=
var dfs func(node *TreeNode) int dfs = func(node *TreeNode) int { if node == nil { return COVERED }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/greedy-algorithm/455-assign-cookies.md)
```go func twoSum(nums []int, target int) []int { seen := make(map[int]int, len(nums))
```go func commonChars(words []string) []string { counts := make([]int, 26)
```go import "sort"
```go func isHappy(n int) bool { visited := make(map[int]struct{})
```go func isAnagram(s string, t string) bool { counts := make([]int, 26)
```go func intersection(nums1 []int, nums2 []int) []int { if len(nums1) > len(nums2) { return intersection(nums2, nums1) }
```go func canConstruct(ransomNote string, magazine string) bool { if len(magazine) < len(ransomNote) { return false }
```go func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int { sum12 := make(map[int]int, len(nums1))
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/hash-table/242-valid-anagram.md)
if length % 2 == 1 { return false }
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func detectCycle(head *ListNode) *ListNode { fast, slow := head, head
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func getIntersectionNode(headA, headB *ListNode) *ListNode { pA, pB := hea
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNod
```cpp /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func reverseList(head *ListNode) *ListNode { cur := head var pre *ListNode
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */
```cpp class MyLinkedList { private: class MyNode { public: int val; MyNode* next;
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/linked-list/203-remove-linked-list-elements.md)
l, r := 0, n - 1 lM, rM := 0, 0 water := 0
for _, x := range nums2 { for len(stack) > 0 && x > stack[len(stack) - 1] { v := stack[len(stack) - 1] stack = stack[: len(stack) - 1] next[v] = x } stack = append(stack, x) } for
for i := 0; i < n; i++ { ans[i] = -1 }
for i := 0; i < n; i++ { for len(stack) > 0 && temperatures[i] > temperatures[stack[len(stack) - 1]] { j := stack[len(stack) - 1] stack = stack[: len(stack) - 1] ans[j] = i - j } s
st := []int{} max := 0
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/monotonic-stack/739-daily-temperatures.md)
for i := 0; i < len(s); i++ { v := s[i]
func evalRPN(tokens []string) int { stack := make([]int, 0, len(tokens))