Go-Python-Java-C-LeetCode高分解法-第四周合集
前言
本题解Go语言部分基于 LeetCode-Go
其他部分基于本人实践学习
个人题解GitHub连接:LeetCode-Go-Python-Java-C
Go-Python-Java-C-LeetCode高分解法-第一周合集
Go-Python-Java-C-LeetCode高分解法-第二周合集
Go-Python-Java-C-LeetCode高分解法-第三周合集
本文部分内容来自网上搜集与个人实践。如果任何信息存在错误,欢迎读者批评指正。本文仅用于学习交流,不用作任何商业用途。
22. Generate Parentheses
题目
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
["((()))","(()())","(())()","()(())","()()()"
]
题目大意
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
解题思路
- 这道题乍一看需要判断括号是否匹配的问题,如果真的判断了,那时间复杂度就到 O(n * 2^n)了,虽然也可以 AC,但是时间复杂度巨高。
- 这道题实际上不需要判断括号是否匹配的问题。因为在 DFS 回溯的过程中,会让
(
和)
成对的匹配上的。
当然,请继续阅读,我会为你分别介绍每个版本的解题思路。
Go 版本解题思路:
这个解题思路使用了深度优先搜索(DFS)的方法来生成有效的括号组合。主要的步骤如下:
-
定义
generateParenthesis
函数,接收括号对数目n
作为参数,返回有效的括号组合列表。 -
如果
n
为 0,直接返回一个空的字符串列表,因为没有括号需要生成。 -
初始化一个空的结果列表
res
,用于存储有效的括号组合。 -
调用辅助函数
findGenerateParenthesis
来递归生成括号组合。传入当前剩余左右括号数目、当前生成的字符串和结果列表的指针。 -
在
findGenerateParenthesis
函数中,当左右括号剩余数目都为 0 时,将当前生成的字符串添加到结果列表中。 -
如果剩余的左括号数目大于 0,可以在当前字符串后添加一个左括号,然后递归生成。
-
如果剩余的右括号数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目(以保证有效性),可以在当前字符串后添加一个右括号,然后递归生成。
-
返回最终的有效括号组合列表
res
。
Python 版本解题思路:
这个解题思路同样使用了深度优先搜索(DFS)的方法来生成有效的括号组合。主要的步骤如下:
-
定义一个
Solution
类,其中有一个generateParenthesis
方法,接收括号对数目n
作为参数,返回有效的括号组合列表。 -
初始化一个空的结果列表
res
,用于存储有效的括号组合。 -
调用递归函数
generate
来生成括号组合。传入当前剩余左右括号数目、当前生成的字符串和结果列表。 -
在
generate
函数中,有两个基准情况:- 如果剩余的左右括号数目都为 0,将当前生成的字符串添加到结果列表中。
- 如果剩余的左括号数目大于 0,可以在当前字符串后添加一个左括号,然后递归生成。
-
如果剩余的右括号数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目(以保证有效性),可以在当前字符串后添加一个右括号,然后递归生成。
-
最后,
generateParenthesis
方法返回最终的有效括号组合列表res
。
Java 版本解题思路:
这个解题思路与前两个版本类似,同样使用深度优先搜索(DFS)的方法来生成有效的括号组合。主要的步骤如下:
-
定义一个
Solution
类,其中有一个generateParenthesis
方法,接收括号对数目n
作为参数,返回有效的括号组合列表。 -
初始化一个空的结果列表
res
,用于存储有效的括号组合。 -
调用递归函数
generate
来生成括号组合。传入当前剩余左右括号数目、当前生成的字符串和结果列表。 -
在
generate
函数中,同样有两个基准情况:- 如果剩余的左右括号数目都为 0,将当前生成的字符串添加到结果列表中。
- 如果剩余的左括号数目大于 0,可以在当前字符串后添加一个左括号,然后递归生成。
-
如果剩余的右括号数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目(以保证有效性),可以在当前字符串后添加一个右括号,然后递归生成。
-
最后,
generateParenthesis
方法返回最终的有效括号组合列表res
。
C++ 版本解题思路:
这个解题思路与其他版本相似,同样使用深度优先搜索(DFS)的方法来生成有效的括号组合。主要的步骤如下:
-
定义一个
Solution
类,其中有一个generateParenthesis
方法,接收括号对数目n
作为参数,返回有效的括号组合列表。 -
初始化一个空的结果列表
res
,用于存储有效的括号组合。 -
调用递归函数
generate
来生成括号组合。传入当前剩余左右括号数目、当前生成的字符串和结果列表。 -
在
generate
函数中,同样有两个基准情况:- 如果剩余的左右括号数目都为 0,将当前生成的字符串添加到结果列表中。
- 如果剩余的左括号数目大于 0,可以在当前字符串后添加一个左括号,然后递归生成。
-
如果剩余的右括号数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目(以保证有效性),可以在当前字符串后添加一个右括号,然后递归生成。
-
最后,
generateParenthesis
方法返回最终的有效括号组合列表res
。
代码
Go
// 定义一个函数 generateParenthesis,输入参数 n 表示括号对数目,返回有效的括号组合列表。
func generateParenthesis(n int) []string {// 如果括号对数目为 0,直接返回一个空的字符串列表。if n == 0 {return []string{}}// 初始化一个结果列表用于存储有效的括号组合。res := []string{}// 调用辅助函数 findGenerateParenthesis 生成括号组合,传入当前左右括号剩余数目、当前生成的字符串和结果列表的指针。findGenerateParenthesis(n, n, "", &res)// 返回最终的有效括号组合列表。return res
}// 定义辅助函数 findGenerateParenthesis,用于递归生成有效的括号组合。
func findGenerateParenthesis(lindex, rindex int, str string, res *[]string) {// 当左右括号剩余数目都为 0 时,说明已经生成了一个有效的括号组合,将其添加到结果列表中。if lindex == 0 && rindex == 0 {*res = append(*res, str)return}// 如果左括号剩余数目大于 0,可以在当前字符串后添加一个左括号,继续递归生成。if lindex > 0 {findGenerateParenthesis(lindex-1, rindex, str+"(", res)}// 如果右括号剩余数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目,// 则可以在当前字符串后添加一个右括号,继续递归生成。if rindex > 0 && lindex < rindex {findGenerateParenthesis(lindex, rindex-1, str+")", res)}
}
Python
class Solution:def generateParenthesis(self, n: int) -> List[str]:res = [] # 存储最终的有效括号组合列表self.generate(n, n, "", res) # 调用递归函数生成括号组合return res# 递归生成括号组合的辅助函数def generate(self, left: int, right: int, current: str, res: List[str]):# 当左右括号剩余数目都为 0 时,说明已经生成了一个有效的括号组合,将其添加到结果列表中。if left == 0 and right == 0:res.append(current)return# 如果左括号剩余数目大于 0,可以在当前字符串后添加一个左括号,继续递归生成。if left > 0:self.generate(left - 1, right, current + "(", res)# 如果右括号剩余数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目,# 则可以在当前字符串后添加一个右括号,继续递归生成。if right > 0 and left < right:self.generate(left, right - 1, current + ")", res)
Java
import java.util.ArrayList;
import java.util.List;class Solution {public List<String> generateParenthesis(int n) {List<String> res = new ArrayList<>(); // 存储最终的有效括号组合列表generate(n, n, "", res); // 调用递归函数生成括号组合return res;}// 递归生成括号组合的辅助函数private void generate(int left, int right, String current, List<String> res) {// 当左右括号剩余数目都为 0 时,说明已经生成了一个有效的括号组合,将其添加到结果列表中。if (left == 0 && right == 0) {res.add(current);return;}// 如果左括号剩余数目大于 0,可以在当前字符串后添加一个左括号,继续递归生成。if (left > 0) {generate(left - 1, right, current + "(", res);}// 如果右括号剩余数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目,// 则可以在当前字符串后添加一个右括号,继续递归生成。if (right > 0 && left < right) {generate(left, right - 1, current + ")", res);}}public static void main(String[] args) {Solution solution = new Solution();int n = 3; // 设置括号对数目List<String> result = solution.generateParenthesis(n); // 调用生成函数for (String str : result) {System.out.println(str); // 输出生成的括号组合}}
}
Cpp
#include <iostream>
#include <vector>
using namespace std;class Solution {
public:vector<string> generateParenthesis(int n) {vector<string> res; // 存储最终的有效括号组合列表generate(n, n, "", res); // 调用递归函数生成括号组合return res;}// 递归生成括号组合的辅助函数void generate(int left, int right, string current, vector<string>& res) {// 当左右括号剩余数目都为 0 时,说明已经生成了一个有效的括号组合,将其添加到结果列表中。if (left == 0 && right == 0) {res.push_back(current);return;}// 如果左括号剩余数目大于 0,可以在当前字符串后添加一个左括号,继续递归生成。if (left > 0) {generate(left - 1, right, current + "(", res);}// 如果右括号剩余数目大于 0,并且剩余的右括号数目严格大于剩余的左括号数目,// 则可以在当前字符串后添加一个右括号,继续递归生成。if (right > 0 && left < right) {generate(left, right - 1, current + ")", res);}}
};
每个版本代码所需要的基础知识。
Go 版本基础知识:
-
函数声明与调用: 了解如何声明和调用函数,Go 使用
func
关键字来定义函数。 -
条件语句: 了解
if
条件语句的用法,以及如何使用条件判断。 -
切片(Slices): 切片是 Go 中灵活的数据结构,类似于动态数组。了解如何声明、初始化和操作切片。
-
递归: 了解递归的概念,以及如何在函数中调用自身。
-
指针与引用: 了解 Go 中的指针和引用,因为函数中需要通过引用传递结果列表。
Python 版本基础知识:
-
函数定义与调用: 理解如何定义和调用函数,Python 使用
def
关键字来声明函数。 -
条件语句: 理解
if
条件语句的语法,以及如何使用条件判断。 -
列表(Lists): 列表是 Python 中常用的数据结构,类似于动态数组。了解如何创建、修改和操作列表。
-
递归: 理解递归的概念,以及如何在函数中调用自身。
Java 版本基础知识:
-
函数声明与调用: 了解如何声明和调用函数,Java 使用方法(methods)来定义函数。
-
条件语句: 了解
if
条件语句的语法,以及如何进行条件判断。 -
列表(Lists): 在 Java 中,可以使用
ArrayList
类作为动态数组。了解如何创建、修改和操作 ArrayList。 -
递归: 了解递归的概念,以及如何在方法中调用自身。
-
类与对象: Java 是面向对象的编程语言,理解类和对象的概念,以及如何定义和使用它们。
C++ 版本基础知识:
-
函数声明与调用: 了解如何声明和调用函数,C++ 使用函数(functions)来定义函数。
-
条件语句: 理解
if
条件语句的语法,以及如何进行条件判断。 -
向量(Vectors): 在 C++ 中,可以使用
vector
类作为动态数组。了解如何创建、修改和操作向量。 -
递归: 理解递归的概念,以及如何在函数中调用自身。
-
类与对象: C++ 也是面向对象的编程语言,理解类和对象的概念,以及如何定义和使用它们。
23. Merge k Sorted Lists
题目
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example :
Input:
[1->4->5,1->3->4,2->6
]
Output: 1->1->2->3->4->4->5->6
题目大意
合并 K 个有序链表
解题思路
Go 版本解法:
这个解法使用了分治的思想来合并 k 个有序链表。首先,判断输入的链表数组的长度:
- 如果长度为 0,返回
nil
。 - 如果长度为 1,直接返回该链表。
对于长度大于 1 的情况,将链表数组分成两半,然后递归地合并左半部分和右半部分,最后将两部分合并。合并的过程是通过一个辅助函数来实现的,比较两个链表的当前节点值,选择较小的节点连接到合并后的链表。
Python 版本解法:
这个解法使用了优先队列(堆)来合并 k 个有序链表。首先,将每个链表的头节点及其值和索引放入优先队列中。然后,循环从优先队列中弹出最小值的节点,将其连接到合并链表的末尾。如果弹出的节点还有下一个节点,将下一个节点入队。
这样,通过不断弹出最小节点,不断将下一个节点入队,就能够逐步构建合并后的链表。
Java 版本解法:
这个解法也是使用了优先队列(堆)来合并 k 个有序链表。与 Python 版本类似,首先将每个链表的头节点及其值和索引放入优先队列中。然后,循环从优先队列中弹出最小值的节点,将其连接到合并链表的末尾。如果弹出的节点还有下一个节点,将下一个节点入队。
这个过程会不断弹出最小节点,不断将下一个节点入队,从而构建合并后的链表。
C++ 版本解法:
这个解法使用了分治的思想来合并 k 个有序链表。首先,定义了一个辅助函数 merge
,用来合并两个有序链表。然后,使用递归的分治方法,将 k 个链表分成两半,递归地合并左半部分和右半部分,最后将两部分合并。
在合并的过程中,辅助函数 merge
会比较两个链表的当前节点值,选择较小的节点连接到合并后的链表。
以上就是各个版本的解题思路,它们都是通过合并有序链表来实现的,但采用了不同的数据结构和算法来达到相同的目标。## 代码
Go
/*** 定义单链表节点结构* type ListNode struct {* Val int // 当前节点的值* Next *ListNode // 指向下一个节点的指针* }*/
func mergeKLists(lists []*ListNode) *ListNode {// 获取输入链表数组的长度len := len(lists)// 根据不同情况进行合并操作switch len {case 0:return nil // 如果没有链表,返回 nilcase 1:return lists[0] // 如果只有一个链表,直接返回这个链表default:mid := len / 2 // 将链表数组分成两半left := mergeKLists(lists[:mid]) // 递归地合并左半部分right := mergeKLists(lists[mid:]) // 递归地合并右半部分return merge(left, right) // 合并左右两部分链表}
}func merge(list1 *ListNode, list2 *ListNode) *ListNode {dummy := &ListNode{} // 创建一个哑节点作为合并后的链表的起始节点cur := dummy // 创建一个当前节点指针,初始指向哑节点// 比较两个链表的节点值,逐个选择较小的节点连接到合并后的链表for list1 != nil && list2 != nil {if list1.Val < list2.Val {cur.Next = list1list1 = list1.Next} else {cur.Next = list2list2 = list2.Next}cur = cur.Next}// 将剩余的 list1 链接到合并后的链表for list1 != nil {cur.Next = list1list1 = list1.Nextcur = cur.Next}// 将剩余的 list2 链接到合并后的链表for list2 != nil {cur.Next = list2list2 = list2.Nextcur = cur.Next}return dummy.Next // 返回合并后链表的起始节点
}
Python
import heapq
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:heap = [] # 使用一个最小堆来存储当前每个链表的头节点for i, node in enumerate(lists):if node:heapq.heappush(heap, (node.val, i, node)) # 将链表头节点的值、链表索引和链表头节点元组入堆dummy = ListNode() # 创建哑节点作为合并后链表的起始节点cur = dummy # 创建一个当前节点指针,初始指向哑节点while heap:val, idx, node = heapq.heappop(heap) # 弹出堆顶元素,即最小值的节点cur.next = node # 将最小节点接到合并链表的末尾cur = cur.nextif node.next:heapq.heappush(heap, (node.next.val, idx, node.next)) # 将下一个节点入堆,保持堆的有序性return dummy.next # 返回合并后链表的起始节点
Java
import java.util.*;
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeKLists(ListNode[] lists) {// 创建一个最小堆,并根据节点值进行比较PriorityQueue<ListNode> minHeap = new PriorityQueue<>((a, b) -> a.val - b.val);// 将所有链表的头节点加入堆for (ListNode node : lists) {if (node != null) {minHeap.offer(node);}}ListNode dummy = new ListNode(); // 创建哑节点作为合并后链表的起始节点ListNode cur = dummy; // 创建一个当前节点指针,初始指向哑节点while (!minHeap.isEmpty()) {ListNode minNode = minHeap.poll(); // 弹出堆顶元素,即最小值的节点cur.next = minNode; // 将最小节点接到合并链表的末尾cur = cur.next;if (minNode.next != null) {minHeap.offer(minNode.next); // 将下一个节点加入堆,保持堆的有序性}}return dummy.next; // 返回合并后链表的起始节点}
}
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* merge(ListNode* list1, ListNode* list2) {if (!list1) return list2;if (!list2) return list1;if (list1->val <= list2->val) {list1->next = merge(list1->next, list2);return list1;} else {list2->next = merge(list1, list2->next);return list2;}}// 使用分治法逐步合并 K 个链表ListNode* quick(vector<ListNode*>& lists, int l, int r) {if (l > r) return nullptr;if (l == r) return lists[l];int mid = (l + r) >> 1;return merge(quick(lists, l, mid), quick(lists, mid + 1, r));}// 主函数,合并 K 个有序链表ListNode* mergeKLists(vector<ListNode*>& lists) {return quick(lists, 0, lists.size() - 1);}
};
每个版本的详细基础知识。
Go 版本解法:
-
链表数据结构: 你需要理解
ListNode
结构的定义,它是一个表示链表节点的结构体,包括一个整数值Val
和指向下一个节点的指针Next
。 -
递归: 这个解法使用了递归来实现分治合并。你需要了解递归的工作原理,即一个函数调用自身以解决更小规模的问题。
-
切片(Slices): Go 中的切片是动态数组,用于存储多个相同类型的元素。解法中用切片进行了链表的分割和合并。
Python 版本解法:
-
优先队列(堆):
heapq
是 Python 中的堆操作库,它提供了优先队列的实现。你需要了解如何使用堆来维护最小元素,以及堆的基本操作。 -
链表数据结构: 你需要理解
ListNode
结构的定义,类似于 Go 版本的链表数据结构。 -
类和对象: Python 是面向对象的语言,解法中使用了类来定义
Solution
类,以及链表节点的构造。 -
循环: 解法中使用了循环来遍历链表、优先队列等。
Java 版本解法:
-
优先队列(堆): Java 中的优先队列也是通过堆实现的,你需要了解如何使用
PriorityQueue
类来创建和操作优先队列。 -
链表数据结构: 你需要理解
ListNode
结构的定义,与其他版本类似。 -
类和对象: Java 也是面向对象的语言,你需要理解类的定义和使用。
-
循环: 解法中使用了循环来遍历链表、优先队列等。
C++ 版本解法:
-
优先队列(堆): C++ 中的
priority_queue
类用于实现优先队列,你需要了解如何使用它来维护最小元素。 -
链表数据结构: 你需要理解
ListNode
结构的定义,与其他版本类似。 -
递归: 解法中使用了递归来实现分治合并,你需要理解递归的概念和用法。
-
类和对象: C++ 是面向对象的语言,解法中使用了类来定义
Solution
类和链表节点。
24. Swap Nodes in Pairs
题目
Given a linked list, swap every two adjacent nodes and return its head.
You may not modify the values in the list’s nodes, only nodes itself may be changed.
Example:
Given 1->2->3->4, you should return the list as 2->1->4->3.
题目大意
两两相邻的元素,翻转链表
解题思路
Go版本:
- 创建一个虚拟节点dummy,将其指向原链表的头节点。
- 使用一个指针pt来遍历链表,直到没有足够的相邻节点可以交换。
- 在每一轮循环中,获取需要交换的相邻节点node1和node2。
- 进行节点交换,即将pt的next指向node2,node1的next指向node2的next,node2的next指向node1。
- 更新指针pt的位置,继续下一轮交换。
- 返回交换相邻节点后的链表头节点。
Python版本:
- 创建一个虚拟节点dummy,将其指向原链表的头节点。
- 使用一个指针pt来遍历链表,直到没有足够的相邻节点可以交换。
- 在每一轮循环中,获取需要交换的相邻节点node1和node2。
- 进行节点交换,即将pt的next指向node2,node1的next指向node2的next,node2的next指向node1。
- 更新指针pt的位置,继续下一轮交换。
- 返回交换相邻节点后的链表头节点。
Java版本:
- 创建一个虚拟节点dummy,将其指向原链表的头节点。
- 使用一个指针pt来遍历链表,直到没有足够的相邻节点可以交换。
- 在每一轮循环中,获取需要交换的相邻节点node1和node2。
- 进行节点交换,即将pt的next指向node2,node1的next指向node2的next,node2的next指向node1。
- 更新指针pt的位置,继续下一轮交换。
- 返回交换相邻节点后的链表头节点。
C++版本:
- 如果链表为空,直接返回原链表头节点。
- 创建一个虚拟节点virNode,将其指向原链表的头节点。
- 使用三个指针p1、p2和p3来进行节点交换。
- 创建一个指针ago,用于记录上一组交换节点的末尾节点。
- 循环遍历链表,直到没有足够的相邻节点可以交换。
- 获取p2的下一个节点。
- 将p2的next指针置为空,然后将p2的next指向p1,将p1的next指向p3,将ago的next指向p2。
- 更新指针ago为p1,指针p1为p3,指针p2为p1的下一个节点。
- 返回交换相邻节点后的链表头节点。## 代码
Go
/*** Definition for singly-linked list.* type ListNode struct {* Val int* Next *ListNode* }*/// 定义一个函数,用于交换链表中相邻节点的位置
func swapPairs(head *ListNode) *ListNode {// 创建一个虚拟节点,指向原链表的头节点dummy := &ListNode{Next: head}// 循环遍历链表,直到没有足够的相邻节点可以交换for pt := dummy; pt != nil && pt.Next != nil && pt.Next.Next != nil; {// 使用多重赋值的方式交换相邻节点的位置pt, pt.Next, pt.Next.Next, pt.Next.Next.Next = pt.Next, pt.Next.Next, pt.Next.Next.Next, pt.Next}// 返回交换相邻节点后的链表头节点的指针return dummy.Next
}
Python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:# 创建一个虚拟节点,指向原链表的头节点dummy = ListNode(0)dummy.next = head# 使用一个指针pt来遍历链表pt = dummy# 循环遍历链表,直到没有足够的相邻节点可以交换while pt.next and pt.next.next:# 获取需要交换的相邻节点node1 = pt.nextnode2 = pt.next.next# 进行节点交换pt.next = node2node1.next = node2.nextnode2.next = node1# 更新指针pt的位置,继续下一轮交换pt = node1# 返回交换相邻节点后的链表头节点return dummy.next
Java
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode swapPairs(ListNode head) {// 创建一个虚拟节点,指向原链表的头节点ListNode dummy = new ListNode(0);dummy.next = head;// 使用一个指针pt来遍历链表ListNode pt = dummy;// 循环遍历链表,直到没有足够的相邻节点可以交换while (pt.next != null && pt.next.next != null) {// 获取需要交换的相邻节点ListNode node1 = pt.next;ListNode node2 = pt.next.next;// 进行节点交换pt.next = node2;node1.next = node2.next;node2.next = node1;// 更新指针pt的位置,继续下一轮交换pt = node1;}// 返回交换相邻节点后的链表头节点return dummy.next;}
}
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* swapPairs(ListNode* head) {// 如果链表为空,直接返回原链表头节点if (!head) return head;// 创建一个虚拟节点,指向原链表的头节点ListNode* virNode = new ListNode(-1);virNode->next = head;// 使用三个指针p1、p2和p3来进行节点交换ListNode* p1 = head;ListNode* p2 = p1->next;ListNode* p3;// 创建一个指针ago,用于记录上一组交换节点的末尾节点ListNode* ago = virNode;// 循环遍历链表,直到没有足够的相邻节点可以交换while (p2) {// 获取p2的下一个节点p3 = p2->next;// 将p2的next指针置为空,然后将p2的next指向p1,将p1的next指向p3,将ago的next指向p2p2->next = nullptr;p2->next = p1;p1->next = p3;ago->next = p2;// 更新指针ago为p1,指针p1为p3,指针p2为p1的下一个节点ago = p1;p1 = p3;if (!p1) {break;} else {p2 = p1->next;}}// 返回交换相邻节点后的链表头节点return virNode->next;}
};
Go 版本:
- 掌握 Go 中的结构体(struct)的定义方法,ListNode 表示节点。
- 理解指针概念,p 用于遍历指向每个节点。
- 了解 for 循环的语法,通过判断指针是否为 nil 来结束。
- 知道如何访问结构体成员,通过指针 p.Next。
- 了解 Make 函数来分配结构体的方法,dummy := &ListNode{0, head}
C++ 版本:
- 掌握 C++ 中的结构体(struct)的定义和使用。本题中用结构体 ListNode 表示链表节点。
- 了解 C++ 中指针的概念。p 是表示当前节点的指针,通过 p->next 访问后继节点。
- 知道 while 循环的写法,循环条件是判断指针是否为空。
- 理解引用传递, ListNode* 表示传递的是指针的引用。
- 知道如何动态创建结构体对象,这里用 ListNode dummy(0) 创建一个虚拟头节点。
Java 版本:
- 掌握 Java 中的类(class)和对象的概念。ListNode 类表示节点对象。
- 理解 Java 中引用传递,ListNode 类型表示对象引用。
- 知道 Java 的 while 循环写法,循环条件是判断引用是否为 null。
- 能够通过引用访问对象的成员,如 n1.next。
- 掌握创建对象的语法,new ListNode(0) 创建一个节点对象。
Python 版本:
- 了解 Python 中的类(class)的概念,ListNode 类表示节点。
- 掌握 Python 的 while 循环语法,通过判断变量是否为 None 来结束循环。
- 理解 Python 中的对象引用,p 和 n1 等都是对对象的引用。
- 能使用 . 属性访问对象成员,如 p.next。
- 知道如何创建类的实例,dummy = ListNode(0) 来创建对象。
25. Reverse Nodes in k-Group
题目
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a
multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5For k = 2, you should return: 2->1->4->3->5For k = 3, you should return: 3->2->1->4->5
Note:
- Only constant extra memory is allowed.
- You may not alter the values in the list’s nodes, only nodes itself may be changed.
题目大意
按照每 K 个元素翻转的方式翻转链表。如果不满足 K 个元素的就不翻转。
解题思路
这一题是 problem 24 的加强版,problem 24 是两两相邻的元素,翻转链表。而 problem 25 要求的是 k 个相邻的元素,翻转链表,problem
相当于是 k = 2 的特殊情况。
Go 版本解题思路:
-
创建一个
reverseKGroup
函数,该函数接收一个头节点和一个整数 k,用于翻转每 k 个节点。 -
在
reverseKGroup
函数中,使用一个循环来判断是否剩余 k 个节点。 -
在循环中,调用
reverse
函数来翻转当前的 k 个节点。 -
将当前节点组的头节点连接到下一个节点组的头节点,然后递归处理下一个节点组。
-
最终返回整个链表翻转后的头节点。
-
reverse
函数用于翻转从first
到last
之间的节点,它使用指针操作来实现翻转。
Python 版本解题思路:
-
创建一个
reverseKGroup
方法,该方法接收一个头节点和一个整数 k,用于翻转每 k 个节点。 -
在
reverseKGroup
方法中,使用递归来处理每个节点组。 -
在递归中,调用
reverse
方法来翻转当前的 k 个节点。 -
将当前节点组的头节点连接到下一个节点组的头节点,然后递归处理下一个节点组。
-
最终返回整个链表翻转后的头节点。
-
reverse
方法用于翻转从first
到last
之间的节点,它使用指针操作来实现翻转。
Java 版本解题思路:
-
创建一个
reverseKGroup
方法,该方法接收一个头节点和一个整数 k,用于翻转每 k 个节点。 -
在
reverseKGroup
方法中,使用递归来处理每个节点组。 -
在递归中,调用
reverse
方法来翻转当前的 k 个节点。 -
将当前节点组的头节点连接到下一个节点组的头节点,然后递归处理下一个节点组。
-
最终返回整个链表翻转后的头节点。
-
reverse
方法用于翻转从first
到last
之间的节点,它使用指针操作来实现翻转。
C++ 版本解题思路:
-
创建一个
reverseKGroup
方法,该方法接收一个头节点和一个整数 k,用于翻转每 k 个节点。 -
在
reverseKGroup
方法中,使用循环来处理每个节点组。 -
在循环中,调用
reverse
方法来翻转当前的 k 个节点。 -
将当前节点组的头节点连接到下一个节点组的头节点,然后继续循环处理下一个节点组。
-
最终返回整个链表翻转后的头节点。
-
reverse
方法用于翻转从target
节点开始的 k 个节点,它使用指针操作来实现翻转。
代码
Go
/*** 单链表节点的定义。* type ListNode struct {* Val int* Next *ListNode* }*/// reverseKGroup 函数接收一个头节点和一个整数 k,将链表中每 k 个节点进行翻转操作。
func reverseKGroup(head *ListNode, k int) *ListNode {node := head // 保存头节点的引用,用于后面返回for i := 0; i < k; i++ {if node == nil {return head // 如果剩余节点不足 k 个,不进行翻转,直接返回头节点}node = node.Next // 移动节点指针到下一个节点}newHead := reverse(head, node) // 调用 reverse 函数翻转当前的 k 个节点head.Next = reverseKGroup(node, k) // 递归处理剩余节点,并将返回的头节点连接到当前节点组的末尾return newHead // 返回翻转后的头节点
}// reverse 函数用于将从 first 到 last 之间的节点进行翻转,返回翻转后的头节点。
func reverse(first *ListNode, last *ListNode) *ListNode {prev := last // prev 指向翻转后的链表末尾,初始为 lastfor first != last {tmp := first.Next // 保存下一个节点的引用first.Next = prev // 将当前节点的 Next 指向 prev,实现翻转prev = first // 更新 prev 为当前节点,以便下一轮循环使用first = tmp // 更新 first 为下一个节点,以便下一轮循环使用}return prev // 返回翻转后的头节点
}
Python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = nextclass Solution:def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:node = head # 保存头节点的引用,用于后面返回for i in range(k):if not node:return head # 如果剩余节点不足 k 个,不进行翻转,直接返回头节点node = node.next # 移动节点指针到下一个节点new_head = self.reverse(head, node) # 调用 reverse 函数翻转当前的 k 个节点head.next = self.reverseKGroup(node, k) # 递归处理剩余节点,并将返回的头节点连接到当前节点组的末尾return new_head # 返回翻转后的头节点# reverse 函数用于将从 first 到 last 之间的节点进行翻转,返回翻转后的头节点。def reverse(self, first: Optional[ListNode], last: Optional[ListNode]) -> Optional[ListNode]:prev = last # prev 指向翻转后的链表末尾,初始为 lastwhile first != last:tmp = first.next # 保存下一个节点的引用first.next = prev # 将当前节点的 next 指向 prev,实现翻转prev = first # 更新 prev 为当前节点,以便下一轮循环使用first = tmp # 更新 first 为下一个节点,以便下一轮循环使用return prev # 返回翻转后的头节点
Java
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode reverseKGroup(ListNode head, int k) {ListNode node = head; // 保存头节点的引用,用于后面返回for (int i = 0; i < k; i++) {if (node == null) {return head; // 如果剩余节点不足 k 个,不进行翻转,直接返回头节点}node = node.next; // 移动节点指针到下一个节点}ListNode newHead = reverse(head, node); // 调用 reverse 函数翻转当前的 k 个节点head.next = reverseKGroup(node, k); // 递归处理剩余节点,并将返回的头节点连接到当前节点组的末尾return newHead; // 返回翻转后的头节点}// reverse 函数用于将从 first 到 last 之间的节点进行翻转,返回翻转后的头节点。private ListNode reverse(ListNode first, ListNode last) {ListNode prev = last; // prev 指向翻转后的链表末尾,初始为 lastwhile (first != last) {ListNode tmp = first.next; // 保存下一个节点的引用first.next = prev; // 将当前节点的 next 指向 prev,实现翻转prev = first; // 更新 prev 为当前节点,以便下一轮循环使用first = tmp; // 更新 first 为下一个节点,以便下一轮循环使用}return prev; // 返回翻转后的头节点}
}
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:// 主函数,翻转每 k 个节点的组ListNode* reverseKGroup(ListNode* head, int k) {auto cur = head; // 当前组的头节点ListNode* prev_tail = nullptr; // 上一组的尾节点ListNode *cur_head = nullptr; // 当前组的头节点ListNode *cur_tail = nullptr; // 当前组的尾节点ListNode *next_cur = nullptr; // 下一个组的头节点ListNode *ans = nullptr; // 最终翻转后的链表的头节点// 循环处理每个组do {// 调用 reverse 函数翻转当前的 k 个节点next_cur = reverse(cur, cur_head, cur_tail, k);if(!ans) {ans = cur_head; // 如果 ans 为空,将当前组的头节点作为答案的头节点}if(prev_tail) {prev_tail->next = cur_head; // 将上一组的尾节点与当前组的头节点相连}prev_tail = cur_tail; // 更新 prev_tail 为当前组的尾节点cur = next_cur; // 将 cur 更新为下一个组的头节点} while(next_cur);cur_tail->next = next_cur; // 将最后一个组的尾节点与下一个组的头节点相连return ans; // 返回整个翻转后的链表头节点}// 辅助函数,翻转从 target 节点开始的 k 个节点ListNode* reverse(ListNode *target, ListNode *(&ret_head), ListNode *(&ret_tail), int k) {if(!target->next) {ret_head = target;ret_tail = target;return nullptr; // 如果 target 节点后面没有节点了,返回空,表明不需要翻转}int cnt = 1;ListNode *tmp = target;for(; tmp->next != nullptr; tmp=tmp->next) {if(cnt >= k ) {break;}cnt++;}if(cnt < k) {ret_head = target;ret_tail = tmp;return nullptr; // 如果剩余节点数量不足 k,返回空,表明不需要翻转}ret_tail = target; // 更新当前组的尾节点为 targetauto cur = target;auto next = target->next;cnt = 1;while(next && cnt < k) {auto next_next = next->next;next->next = cur;cur = next;next = next_next;cnt++;}ret_head = cur; // 更新当前组的头节点为 curret_tail->next = nullptr; // 将当前组的尾节点的 next 指向空,表示该组翻转后的尾节点return next; // 返回下一个组的头节点}
};
Go 版本代码:
结构体与指针: Go 使用结构体表示链表节点,这是一种自定义的数据结构。代码中的 ListNode 结构体有一个整数字段 Val 和一个指向下一个节点的指针字段 Next。head 是指向链表头节点的指针。
递归: reverseKGroup 函数使用递归来处理每一组节点的翻转。递归是一种重要的编程技巧,它可以在解决问题时将问题拆分成更小的相同子问题。
Python 版本代码:
类与方法: Python 使用类来定义链表节点,代码中的 ListNode 类包含整数字段 val 和指向下一个节点的引用字段 next。Solution 类定义了处理问题的方法。
递归: 与 Go 版本相同,Python 版本也使用递归来处理每一组节点的翻转。
Java 版本代码:
类与方法: Java 也使用类来定义链表节点,代码中的 ListNode 类有一个整数字段 val 和一个指向下一个节点的引用字段 next。Solution 类定义了处理问题的方法。
递归: 与 Go 和 Python 版本类似,Java 版本也使用递归来处理每一组节点的翻转。
C++ 版本代码:
类与指针: C++ 使用 struct 结构体来定义链表节点,代码中的 ListNode 结构体有一个整数字段 val 和一个指向下一个节点的指针字段 next。Solution 类定义了处理问题的方法。
递归: 与其他版本一样,C++ 版本也使用递归来处理每一组节点的翻转。
指针操作: C++ 版本中涉及指针的操作,如节点的指针赋值、遍历等。理解指针的基本概念和操作对于理解这些代码是很重要的。
26. Remove Duplicates from Sorted Array
题目
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,2],Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,0,1,1,1,2,2,3,3,4],Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeElement(nums, val);// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {print(nums[i]);
}
题目大意
给定一个有序数组 nums,对数组中的元素进行去重,使得原数组中的每个元素只有一个。最后返回去重以后数组的长度值。
解题思路
Go 版本解题思路:
- 初始化一个指针
i
,用于指向当前不重复元素的位置。 - 使用两个指针,
i
和j
,其中i
指向当前不重复元素的位置,而j
用于遍历数组。 - 从数组的第二个元素开始,遍历数组。比较当前元素和前一个元素是否相等。
- 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素,将指针
i
向前移动一位,然后将当前不重复的元素放置在指针i
的位置。 - 重复步骤 3 和 4,直到遍历完整个数组。
- 返回不重复元素的数量(长度),需要加 1,因为数组下标从 0 开始。
Python 版本解题思路:
- 初始化一个指针
i
,用于指向当前不重复元素的位置。 - 使用两个指针,
i
和j
,其中i
指向当前不重复元素的位置,而j
用于遍历列表。 - 从列表的第二个元素开始,遍历列表。比较当前元素和前一个元素是否相等。
- 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素,将指针
i
向前移动一位,然后将当前不重复的元素放置在指针i
的位置。 - 重复步骤 3 和 4,直到遍历完整个列表。
- 返回不重复元素的数量(长度),需要加 1,因为列表下标从 0 开始。
Java 版本解题思路:
- 初始化一个指针
i
,用于指向当前不重复元素的位置。 - 使用两个指针,
i
和j
,其中i
指向当前不重复元素的位置,而j
用于遍历数组。 - 从数组的第二个元素开始,遍历数组。比较当前元素和前一个元素是否相等。
- 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素,将指针
i
向前移动一位,然后将当前不重复的元素放置在指针i
的位置。 - 重复步骤 3 和 4,直到遍历完整个数组。
- 返回不重复元素的数量(长度),需要加 1,因为数组下标从 0 开始。
C++ 版本解题思路:
- 初始化一个指针
i
,用于指向当前不重复元素的位置。 - 使用两个指针,
i
和j
,其中i
指向当前不重复元素的位置,而j
用于遍历向量。 - 从向量的第二个元素开始,遍历向量。比较当前元素和前一个元素是否相等。
- 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素,将指针
i
向前移动一位,然后将当前不重复的元素放置在指针i
的位置。 - 重复步骤 3 和 4,直到遍历完整个向量。
- 返回不重复元素的数量(长度),需要加 1,因为向量下标从
代码
Go
// 定义一个函数,用于从排序后的整数数组中去除重复元素,并返回新数组的长度
func removeDuplicates(nums []int) int {// 如果数组为空,直接返回0if len(nums) == 0 {return 0}// 初始化一个指针i,用于指向当前不重复元素的位置i := 0// 遍历数组,从第二个元素开始for j := 1; j < len(nums); j++ {// 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素if nums[i] != nums[j] {// 将指针i向前移动一位i++// 将当前不重复的元素放置在指针i的位置nums[i] = nums[j]}}// 返回不重复元素的数量(长度),需要加1,因为数组下标从0开始return i + 1
}
Python
class Solution:def removeDuplicates(self, nums: List[int]) -> int:# 如果数组为空,直接返回0if not nums:return 0# 初始化一个指针i,用于指向当前不重复元素的位置i = 0# 遍历数组,从第二个元素开始for j in range(1, len(nums)):# 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素if nums[i] != nums[j]:# 将指针i向前移动一位i += 1# 将当前不重复的元素放置在指针i的位置nums[i] = nums[j]# 返回不重复元素的数量(长度),需要加1,因为数组下标从0开始return i + 1
Java
class Solution {public int removeDuplicates(int[] nums) {// 如果数组为空,直接返回0if (nums.length == 0) {return 0;}// 初始化一个指针i,用于指向当前不重复元素的位置int i = 0;// 遍历数组,从第二个元素开始for (int j = 1; j < nums.length; j++) {// 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素if (nums[i] != nums[j]) {// 将指针i向前移动一位i++;// 将当前不重复的元素放置在指针i的位置nums[i] = nums[j];}}// 返回不重复元素的数量(长度),需要加1,因为数组下标从0开始return i + 1;}
}
Cpp
#include <vector>class Solution {
public:int removeDuplicates(std::vector<int>& nums) {// 如果数组为空,直接返回0if (nums.empty()) {return 0;}// 初始化一个指针i,用于指向当前不重复元素的位置int i = 0;// 遍历数组,从第二个元素开始for (int j = 1; j < nums.size(); j++) {// 如果当前元素不等于前一个元素,说明找到了一个新的不重复元素if (nums[i] != nums[j]) {// 将指针i向前移动一位i++;// 将当前不重复的元素放置在指针i的位置nums[i] = nums[j];}}// 返回不重复元素的数量(长度),需要加1,因为数组下标从0开始return i + 1;}
};
Go 版本解法所需基础知识:
- 切片(Slices)和数组(Arrays): Go 中的切片是动态数组,可以根据需要动态调整大小。在本题中,我们使用切片来操作数组。
- 循环和迭代: 你需要理解
for
循环和如何迭代数组的元素。 - 指针:
i
是一个指向数组元素的指针,你需要了解指针的概念和如何使用它来修改数组元素。
Python 版本解法所需基础知识:
- 列表(Lists): Python 中的列表类似于数组,可以包含多个元素。在本题中,我们使用列表来操作数组。
- 循环和迭代: 你需要理解
for
循环和如何迭代列表的元素。 - 索引和切片: 你需要了解如何使用索引来访问列表元素,以及如何使用切片来修改和操作列表。
Java 版本解法所需基础知识:
- 数组: Java 中的数组是一组相同类型的元素的集合。在本题中,我们使用数组来存储和操作元素。
- 循环和迭代: 你需要理解
for
循环和如何迭代数组的元素。 - 数组索引: 你需要了解如何使用索引来访问数组元素,并理解数组索引从 0 开始的概念。
C++ 版本解法所需基础知识:
- 向量(Vectors): C++ 中的向量类似于数组,是一种动态数组容器。在本题中,我们使用向量来存储和操作元素。
- 循环和迭代: 你需要理解
for
循环和如何迭代向量的元素。 - 数组索引: 你需要了解如何使用索引来访问向量元素,并理解数组索引从 0 开始的概念。
27. Remove Element
题目
Given an array nums and a value val, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.
Example 1:
Given nums = [3,2,2,3], val = 3,Your function should return length = 2, with the first two elements of nums being 2.It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,1,2,2,3,0,4,2], val = 2,Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.Note that the order of those five elements can be arbitrary.It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeElement(nums, val);// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {print(nums[i]);
}
题目大意
给定一个数组 nums 和一个数值 val,将数组中所有等于 val 的元素删除,并返回剩余的元素个数。
解题思路
以下是每个版本的解题思路的详细介绍:
Go 版本解题思路:
-
使用两个指针
left
和right
分别初始化为 0 和切片nums
的长度。left
指向数组的起始位置,right
指向数组的结束位置。 -
使用一个循环,条件是
left
小于right
,表示只要left
还在right
的左边,就继续执行循环。 -
在循环中,检查
nums[left]
是否等于目标值val
。如果相等,说明需要将这个元素删除。 -
如果相等,将
nums[left]
的值替换为nums[right-1]
的值,同时将right
减 1,相当于将目标值移到数组的末尾。这一步不需要真正删除元素,只是覆盖了数组中的值。 -
如果
nums[left]
不等于目标值val
,将left
向右移动一位,继续检查下一个元素。 -
循环结束后,返回
left
的值,即新数组的长度,因为所有等于目标值val
的元素都被移到数组末尾,而剩余元素的个数就是left
的值。
Python 版本解题思路:
-
初始化两个指针
fast
和slow
,初始都为 0。 -
使用一个循环遍历数组
nums
,条件是fast
小于数组的长度。 -
如果
nums[slow]
不等于目标值val
,将slow
指针向后移动一位,以保留当前元素。 -
如果
nums[slow]
等于目标值val
,需要删除该元素。使用另一个循环,将后面的元素逐个左移,覆盖掉当前元素,直到将目标值val
移除。 -
每次循环结束后,将
fast
指针向后移动一位,以继续遍历下一个元素。 -
循环结束后,
slow
的值表示新数组的长度,返回slow
。
Java 版本解题思路:
-
初始化两个指针
left
和right
,其中left
指向数组的起始位置,right
指向数组的结束位置。 -
使用一个循环,条件是
left
小于right
,表示只要left
还在right
的左边,就继续执行循环。 -
在循环中,检查
nums[left]
是否等于目标值val
。如果相等,说明需要将这个元素删除。 -
如果相等,将
nums[left]
的值替换为nums[right-1]
的值,同时将right
减 1,相当于将目标值移到数组的末尾。这一步不需要真正删除元素,只是覆盖了数组中的值。 -
如果
nums[left]
不等于目标值val
,将left
向右移动一位,继续检查下一个元素。 -
循环结束后,返回
left
的值,即新数组的长度,因为所有等于目标值val
的元素都被移到数组末尾,而剩余元素的个数就是left
的值。
C++ 版本解题思路:
-
初始化两个指针
left
和right
,其中left
指向向量的起始位置,right
指向向量的结束位置。 -
使用一个循环,条件是
left
小于right
,表示只要left
还在right
的左边,就继续执行循环。 -
在循环中,检查
nums[left]
是否等于目标值val
。如果相等,说明需要将这个元素删除。 -
如果相等,将
nums[left]
的值替换为nums[right-1]
的值,同时将right
减 1,相当于将目标值移到数组的末尾。这一步不需要真正删除元素,只是覆盖了数组中的值。 -
如果
nums[left]
不等于目标值val
,将left
向右移动一位,继续检查下一个元素。 -
循环结束后,返回
left
的值,即新向量的长度,因为所有等于目标值val
的元素都被移到向量末尾,而剩余元素的个数就是left
的值。
代码
Go
func removeElement(nums []int, val int) int {// 定义左右两个指针,初始位置分别为切片的起始位置和结束位置left, right := 0, len(nums)// 使用循环,当左指针小于右指针时,继续执行操作for left < right {// 如果左指针指向的元素等于目标值 valif nums[left] == val {// 将左指针指向的元素替换为右指针指向的元素// 同时将右指针向左移动一位nums[left] = nums[right - 1]right--} else {// 如果左指针指向的元素不等于目标值 val// 则将左指针向右移动一位,继续检查下一个元素left++}}// 循环结束后,左指针的位置就是新切片的长度return left
}
Python
class Solution:def removeElement(self, nums: List[int], val: int) -> int:# 初始化两个指针 fast 和 slow,表示快慢指针fast, slow = 0, 0# 使用 while 循环遍历列表while fast < len(nums):# 如果慢指针指向的元素不等于目标值 valif nums[slow] != val:slow += 1else:# 如果慢指针指向的元素等于目标值 val,需要删除该元素i = slowwhile i < len(nums) - 1:nums[i] = nums[i + 1]i += 1# 快指针向右移动一位fast += 1# 返回慢指针的位置,即新列表的长度return slow
Java
class Solution {public int removeElement(int[] nums, int val) {// 初始化左右两个指针,left指向切片的起始位置,right指向切片的结束位置int left = 0;int right = nums.length;// 遍历数组,当left小于right时,继续执行while (left < right) {// 如果当前元素等于目标值valif (nums[left] == val) {// 将当前元素替换为右指针指向的元素// 同时将右指针向左移动一位nums[left] = nums[right - 1];right--;} else {// 如果当前元素不等于目标值val// 则将左指针向右移动一位,继续检查下一个元素left++;}}// 循环结束后,左指针的位置就是新数组的长度return left;}
}
Cpp
class Solution {
public:int removeElement(vector<int>& nums, int val) {// 初始化左右两个指针,left指向向量的起始位置,right指向向量的结束位置int left = 0;int right = nums.size();// 遍历向量,当left小于right时,继续执行while (left < right) {// 如果当前元素等于目标值valif (nums[left] == val) {// 将当前元素替换为右指针指向的元素// 同时将右指针向左移动一位nums[left] = nums[right - 1];right--;} else {// 如果当前元素不等于目标值val// 则将左指针向右移动一位,继续检查下一个元素left++;}}// 循环结束后,left的位置就是新向量的长度return left;}
};
当讨论这些不同编程语言版本的解决方案时,需要了解以下基本知识:
Go 版本
- Go 是一种静态类型的编程语言,具有内存管理和并发支持。
- 在 Go 中,切片是动态数组,是一种引用类型,可以动态扩展。
- 在 Go 中,数组和切片的下标从0开始。
- 了解 for 循环以及条件语句,如 if 语句。
- 掌握指针的概念,因为解决方案使用了两个指针,即
left
和right
。 - Go 使用零值初始化变量,因此需要确保变量的初始状态正确。
Python 版本
- Python 是一种高级的解释型编程语言,具有动态类型。
- Python 中的列表(List)是一种动态数组,可以包含不同类型的元素。
- 理解 while 循环以及条件语句,如 if 语句。
- 掌握列表的基本操作,如访问、修改和删除元素。
- 了解 Python 的索引规则,列表的索引也是从0开始。
Java 版本
- Java 是一种静态类型的编程语言,具有强类型检查和垃圾回收。
- 在 Java 中,数组是一种固定大小的数据结构,不能动态扩展。因此,需要使用新的数组来实现元素的删除操作。
- 掌握类和方法的定义,以及循环结构,如 while 循环。
- 了解数组的基本操作,包括访问和修改元素。
C++ 版本
- C++ 是一种静态类型的编程语言,具有高性能和低级内存控制。
- 在 C++ 中,使用标准库容器
vector
来表示动态数组,也可以使用数组。 - 掌握类和方法的定义,以及循环结构,如 while 循环。
- 了解数组或
vector
的基本操作,包括访问和修改元素。
28. Find the Index of the First Occurrence in a String
题目
Implement strStr().
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = "hello", needle = "ll"
Output: 2
Example 2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1
Clarification:
What should we return when needle is an empty string? This is a great question to ask during an interview.
For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strstr() and Java’s indexOf().
题目大意
实现一个查找 substring 的函数。如果在母串中找到了子串,返回子串在母串中出现的下标,如果没有找到,返回 -1,如果子串是空串,则返回 0 。
解题思路
Go 版本
解法一:
- 使用两个嵌套的循环,在主字符串
haystack
中迭代每个字符,外循环从i
开始,内循环从j
开始。 - 在内循环中,比较
haystack[i+j]
和needle[j]
,如果不相等,则跳出内循环,继续外循环。 - 如果内循环完成(即
j
等于needle
的长度),则表示找到了匹配的子串,返回i
,即匹配子串在haystack
中的起始索引。 - 如果外循环完成(即
i+j
等于haystack
的长度),仍未找到匹配,返回 -1。
解法二:
- 使用 Go 标准库中的
strings.Index
函数,该函数会在主字符串haystack
中查找子串needle
的第一次出现,并返回其索引。 - 如果找到匹配的子串,则返回索引值;如果未找到,则返回 -1。
Python 版本
解法一:
- 使用两个嵌套的循环,在主字符串
haystack
中迭代每个字符,外循环从i
开始,内循环从j
开始。 - 在内循环中,比较
haystack[i+j]
和needle[j]
,如果不相等,则跳出内循环,继续外循环。 - 如果内循环完成(即
j
等于needle
的长度),则表示找到了匹配的子串,返回i
,即匹配子串在haystack
中的起始索引。 - 如果外循环完成(即
i+j
等于haystack
的长度),仍未找到匹配,返回 -1。
解法二:
- 使用 Python 字符串的内置方法
str.find(needle)
,该方法会在主字符串haystack
中查找子串needle
的第一次出现,并返回其索引。 - 如果找到匹配的子串,则返回索引值;如果未找到,则返回 -1。
Java 版本
解法一:
- 使用两个嵌套的循环,在主字符串
haystack
中迭代每个字符,外循环从i
开始,内循环从j
开始。 - 在内循环中,比较
haystack.charAt(i+j)
和needle.charAt(j)
,如果不相等,则跳出内循环,继续外循环。 - 如果内循环完成(即
j
等于needle
的长度),则表示找到了匹配的子串,返回i
,即匹配子串在haystack
中的起始索引。 - 如果外循环完成(即
i+j
等于haystack
的长度),仍未找到匹配,返回 -1。
解法二:
- 使用 Java 字符串的内置方法
haystack.indexOf(needle)
,该方法会在主字符串haystack
中查找子串needle
的第一次出现,并返回其索引。 - 如果找到匹配的子串,则返回索引值;如果未找到,则返回 -1。
C++ 版本
解法一:
- 使用两个嵌套的循环,在主字符串
haystack
中迭代每个字符,外循环从i
开始,内循环从j
开始。 - 在内循环中,比较
haystack[i+j]
和needle[j]
,如果不相等,则跳出内循环,继续外循环。 - 如果内循环完成(即
j
等于needle
的长度),则表示找到了匹配的子串,返回i
,即匹配子串在haystack
中的起始索引。 - 如果外循环完成(即
i+j
等于haystack
的长度),仍未找到匹配,返回 -1。
解法二:
- 使用 C++ 字符串的内置方法
haystack.find(needle)
,该方法会在主字符串haystack
中查找子串needle
的第一次出现,并返回其索引。 - 如果找到匹配的子串,则返回索引值;如果未找到,则返回 -1。
这些解题思路详细描述了每个版本的代码是如何逐步寻找匹配子串的过程,并在找到匹配时返回相应的索引,或在未找到匹配时返回 -1。
代码
Go
import "strings"// 解法一
func strStr(haystack string, needle string) int {// 外层循环遍历haystack中的每个字符for i := 0; ; i++ {// 内层循环遍历needle中的每个字符for j := 0; ; j++ {// 如果j等于needle的长度,说明needle中的所有字符都已经在haystack中匹配成功if j == len(needle) {return i // 返回匹配成功的起始索引位置i}// 如果i+j等于haystack的长度,说明已经遍历完haystack但仍未找到匹配if i+j == len(haystack) {return -1 // 返回-1表示未找到匹配}// 如果当前needle中的字符与当前haystack中的字符不相等,跳出内层循环if needle[j] != haystack[i+j] {break}}}
}// 解法二
func strStr1(haystack string, needle string) int {// 使用标准库strings的Index函数来查找needle在haystack中的位置// 如果找到,返回第一次出现的索引位置;如果未找到,返回-1return strings.Index(haystack, needle)
}
Python
class Solution:def strStr(self, haystack: str, needle: str) -> int:# 解法一:自己实现的字符串匹配算法for i in range(len(haystack) + 1):for j in range(len(needle) + 1):if j == len(needle):return iif i + j == len(haystack):return -1if needle[j] != haystack[i + j]:breakclass Solution:def strStr(self, haystack: str, needle: str) -> int:# 解法二:使用Python内置函数indexreturn haystack.find(needle)
Java
class Solution {public int strStr(String haystack, String needle) {// 解法一:自己实现的字符串匹配算法for (int i = 0; ; i++) {for (int j = 0; ; j++) {if (j == needle.length()) {return i;}if (i + j == haystack.length()) {return -1;}if (needle.charAt(j) != haystack.charAt(i + j)) {break;}}}}
}
class Solution {public int strStr(String haystack, String needle) {// 解法二:使用Java内置函数indexOfreturn haystack.indexOf(needle);}
}
Cpp
class Solution {
public:int strStr(string haystack, string needle) {// 解法一:自己实现的字符串匹配算法for (int i = 0; ; i++) {for (int j = 0; ; j++) {if (j == needle.length()) {return i;}if (i + j == haystack.length()) {return -1;}if (needle[j] != haystack[i + j]) {break;}}}}
};
class Solution {
public:int strStr(string haystack, string needle) {// 解法二:使用C++内置函数findsize_t index = haystack.find(needle);return index != string::npos ? index : -1;}
};
Go 版本
解法一:
- 字符串操作:需要了解如何访问字符串的字符,字符串的长度等。
- 循环:需要熟悉 for 循环,以便在字符串中进行遍历操作。
- 条件语句:使用条件语句来检查是否匹配子串以及何时返回结果。
- 索引和切片:可以通过索引访问字符串的单个字符,并使用切片来获取子串。
解法二:
- 字符串操作:需要了解 Go 标准库中字符串处理函数的用法,例如
strings.Index
。
Python 版本
解法一:
- 字符串操作:需要了解如何访问字符串的字符,字符串的长度等。
- 循环:需要熟悉 for 循环,以便在字符串中进行遍历操作。
- 条件语句:使用条件语句来检查是否匹配子串以及何时返回结果。
解法二:
- 字符串操作:需要了解 Python 字符串的一些内置方法,如
str.find
。
Java 版本
解法一:
- 字符串操作:需要了解如何访问字符串的字符,字符串的长度等。
- 循环:需要熟悉 for 循环,以便在字符串中进行遍历操作。
- 条件语句:使用条件语句来检查是否匹配子串以及何时返回结果。
解法二:
- 字符串操作:需要了解 Java 字符串的一些内置方法,如
indexOf
。
C++ 版本
解法一:
- 字符串操作:需要了解如何访问字符串的字符,字符串的长度等。
- 循环:需要熟悉 for 循环,以便在字符串中进行遍历操作。
- 条件语句:使用条件语句来检查是否匹配子串以及何时返回结果。
解法二:
- 字符串操作:需要了解 C++ 字符串的一些内置方法,如
find
。 - 数据类型转换:使用
static_cast
进行数据类型转换,因为find
返回的是size_t
类型,而我们需要返回int
类型的结果。
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
Go-Python-Java-C-LeetCode高分解法-第四周合集
前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接:LeetCode-Go-Python-Java-C Go-Python-Java-C-LeetCode高分解法-第一周合集 Go-Python-Java-C-LeetCode高分解法-第二周合集 Go-Python-Java-C-LeetCode高分解法-第三周合集 本…...
![](https://www.ngui.cc/images/no-images.jpg)
vue路由
一、声明式导航-导航链接 1.需求 实现导航高亮效果 如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!! 2.解决方案 vue-router 提供了一个全局组件 router…...
![](https://img-blog.csdnimg.cn/336612802563477cb14f218a3ff07b12.png)
最强的AI视频去码图片修复模型:CodeFormer
目录 1 CodeFormer介绍 1.1 CodeFormer解决的问题 1.2 人脸复原的挑战 1.3 方法动机 1.4 模型实现 1.5 实验结果 2 CodeFormer部署与运行 2.1 conda环境安装 2.2 运行环境构建 2.3 模型下载 2.4 运行 2.4.1 人脸复原 编辑编辑 2.4.2 全图片增强 2.4.3 人脸颜色…...
![](https://www.ngui.cc/images/no-images.jpg)
jenkins自动化部署安装
一、准备工作 1、安装jdk # 1、下载准备jdk包(也可以用docker安装) wget ... # 2、直接解压到,无需安装 unzip ...2、安装maven # 1、下载准备maven压缩包 wget ... # 2、直接解压,无需安装 unzip ... # 3、修改setting.xml,修改localRepository和MIRROR镜像地址…...
![](https://img-blog.csdnimg.cn/d9fda4b9eed943a798ca9098e736e811.png)
如何调用Zabbix API获取主机信息
自Zabbix 1.8版本被引进以后,Zabbix API开始扮演着越来越重要的角色,它可以为批量操作、第三方软件集成以及其他应用提供可编程接口。 在运维实践中,Zabbix API还有更多巧妙的应用。 面对规模庞大的监控设备,可能会出现某台机器发…...
![](https://www.ngui.cc/images/no-images.jpg)
批量执行redis命令总结
目录 批量执行redis命令方式1: redis-cli直接执行方式2:通过redis-cli和xargs等命令 批量执行redis命令 方式1: redis-cli直接执行 redis-cli command param redis-cli本身支持单个命令执行省略了连接参数操作的key等相关数据,可以通过线下获取或通过keys scan等命…...
![](https://img-blog.csdnimg.cn/0ce5daf2c9f549a39185fc695eb4b2c7.png)
命令行git联网失败,但是实际可以联网
最近下载代码的时候发现总是告诉我连不上github的网页,但是我自己通过浏览器又可以上网,找了半天发现这个方法可以。 记录下这个代理 打开git bash 执行以下命令: git config --global http.proxy http://127.0.0.1:7890 git config --glob…...
![](https://img-blog.csdnimg.cn/94fd643703774345b0a8b9d267c83b9e.png)
网络编程套接字,Linux下实现echo服务器和客户端
目录 1、一些网络中的名词 1.1 IP地址 1.2 端口号port 1.3 "端口号" 和 "进程ID" 1.4 初始TCP协议 1.5 UDP协议 2、socket编程接口 2.1 socket 常见API 2.2 sockaddr结构 3、简单的网络程序 3.1 udp实现echo服务器和客户端 3.1.1 echo服务器实…...
![](https://img-blog.csdnimg.cn/c9e93051edee40b39de3bba4a676fc04.png)
java+ssh+mysql智能化办公管理系统
项目介绍: 本系统为基于jspsshmysql的OA智能办公管理系统,包含管理员、领导、员工角色,功能如下: 管理员:公告信息;工作计划;公司资料;部门管理;员工管理;员…...
![](https://www.ngui.cc/images/no-images.jpg)
网络层抓包tcpdump
sudo tcpdump -i eth0 -s 0 -nn host iphost -w xxx.pcap 这段代码使用了命令行工具 tcpdump,用于在Linux系统上捕获网络数据包。让我详细介绍一下这段代码的含义和 tcpdump 的用法: 代码含义: sudo: 使用超级用户权限执行 tcpdump 命令&am…...
![](https://img-blog.csdnimg.cn/7d104c98d39147a38c91c6ff602af3e4.bmp)
QT之形态学操作
形态学操作包含以下操作: 腐蚀 (Erosion)膨胀 (Dilation)开运算 (Opening)闭运算 (Closing)形态梯度 (Morphological Gradient)顶帽 (Top Hat)黑帽(Black Hat) 其中腐蚀和膨胀操作是最基本的操作,其他操作由这两个操作变换而来。 腐蚀 用一个结构元素…...
![](https://img-blog.csdnimg.cn/7c6a0c4452a849e0adff415e1bc069f9.png)
15、监测数据采集物联网应用开发步骤(11)
源码将于最后一遍文章给出下载 监测数据采集物联网应用开发步骤(10) 程序自动更新开发 前面章节写了部分功能模块开发: 日志或文本文件读写开发;Sqlite3数据库读写操作开发;定时器插件化开发;串口(COM)通讯开发;TCP/IP Client开发;TCP/IP Server 开发;modbus协议…...
![](https://www.ngui.cc/images/no-images.jpg)
Pygame中Trivia游戏解析6-2
3.1.2 读取保存题目的文件 在Trivia类的__init__()方法中,对各变量初始化完成之后,读取保存题目的文件,代码如下所示。 f open(filename, "r", encodingutf8) trivia_data f.readlines() f.close() 其中,open()函数…...
![](https://www.ngui.cc/images/no-images.jpg)
java 实现命令行模式
命令模式是一种行为设计模式,它允许您将请求封装为对象,以便您可以将其参数化、队列化、记录和撤销。在 Java 中实现命令模式涉及创建一个命令接口,具体命令类,以及一个接收者类,该接收者类执行实际操作。下面是一个简…...
![](https://www.ngui.cc/images/no-images.jpg)
A - Orac and Models(最长上升子序列——加强版)
There are nn models in the shop numbered from 11 to nn, with sizes s_1, s_2, \ldots, s_ns1,s2,…,sn. Orac will buy some of the models and will arrange them in the order of increasing numbers (i.e. indices, but not sizes). Orac thinks that the obtai…...
![](https://img-blog.csdnimg.cn/f09e9a4963474ed893d8b432fa799c90.png)
【python手写算法】逻辑回归实现分类(含公式推导)
公式推导: 代码实现: # codingutf-8 import matplotlib.pyplot as plt import numpy as npdef f(w1,x1,w2,x2,b):zw1*x1w2*x2breturn 1/(1np.exp(-z)) if __name__ __main__:X1 [12.46, 0.25, 5.22, 11.3, 6.81, 4.59, 0.66, 14.53, 15.49, 14.43,2.1…...
![](https://img-blog.csdnimg.cn/d5202a4ce238464793e04a44c29dd329.png#pic_center)
【2023高教社杯数学建模国赛】ABCD题 问题分析、模型建立、参考文献及实现代码
【2023高教社杯数学建模国赛】ABCD题 问题分析、模型建立、参考文献及实现代码 1 比赛时间 北京时间:2023年9月7日 18:00-2023年9月10日20:00 2 思路内容 可以参考我提供的历史竞赛信息内容,最新更新我会发布在博客和知乎上,请关注我获得最…...
![](https://img-blog.csdnimg.cn/11373eec131a45e1b35f42f54afaa1d1.png)
yum安装mysql5.7散记
## 数据源安装 $ yum -y install wget $ wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm $ yum localinstall mysql57-community-release-el7-8.noarch.rpm $ yum repolist enabled | grep "mysql.*-community.*" $ yum install mysql-…...
![](https://img-blog.csdnimg.cn/8a3bc7b528444837af264835aced2401.png)
DNS解析
1.DNS介绍 DNS 表示域名系统。此系统实质上是用于整理和识别各个域名的网络电话簿。电话簿将“Acme Pizza”之类的名称转换为要拨打的正确电话号码,而 DNS 将“www.google.com”之类的网络地址转换为托管该网站的计算机的物理 IP 地址,如“74.125.19.147…...
![](https://www.ngui.cc/images/no-images.jpg)
从jdk8 升级到jdk17的问题总结
目录 1. java.lang.reflect.InaccessibleObjectException: 2. java.lang.UnsatisfiedLinkError in autosys 3. java.lang.NoClassDefFoundError: Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser 4. java.lang.UnsatisfiedLinkError: **…...
![](https://img-blog.csdnimg.cn/f089f43320234699b5d2029a5335c65e.png)
一百七十二、Flume——Flume采集Kafka数据写入HDFS中(亲测有效、附截图)
一、目的 作为日志采集工具Flume,它在项目中最常见的就是采集Kafka中的数据然后写入HDFS或者HBase中,这里就是用flume采集Kafka的数据导入HDFS中 二、各工具版本 (一)Kafka kafka_2.13-3.0.0.tgz (二)…...
![](https://img-blog.csdnimg.cn/4e19c4fb9f414536b33c6f59b7b97dfa.png)
pnpm 升级
1. 在以下路径下删除pnpm包 2. 执行which pnpm,在结果目录中删除pnpm 3. sudo npm install -g pnpm 重新安装,node默认使用16...
![](https://www.ngui.cc/images/no-images.jpg)
有关使用HttpServletRequest的Cookie的设置和获取
文章目录 小结问题和解决参考 小结 介绍了如何在HttpServletRequest中对Cookie的进行设置和获取。 问题和解决 在服务器端的HttpServletRequest中对Cookie的进行设置后,客户端在接下来的请求中会携带此设置好的Cookie,所以可以在服务器端接收请求时提…...
![](https://www.ngui.cc/images/no-images.jpg)
关于 Nginx 的哪些事
关于 Nginx 的哪些事 1、Nginx 主要功能2、Nginx 的常用命令2.1、启动Nginx2.2、停止 Nginx2.3、重新加载Nginx 配置2.4、检查Nginx配置文件2.5、指定配置文件2.6、检查Nginx版本2.7、显示Nginx帮助信息 3、Nginx 配置文件 nginx.conf3.1、Nginx 配置文件(nginx.con…...
![](https://img-blog.csdnimg.cn/7762cee168dc410dac48a8f10841f2e0.jpeg)
插入排序——希尔排序
1、简述: 希尔排序(Shells Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。 希尔排…...
![](https://csdnimg.cn/release/blog_editor_html/release2.3.6/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=N7T8)
C语言之初阶总结篇
目录 NO.1 NO.2 NO.3 NO.4 NO.5 NO.6 NO.7 NO.8 NO.9 NO.10 NO.11 NO.12.概念tips NO.13.求最小公倍数 NO.14.最大公因数 NO.15.输入读取字符串 NO.16.倒置字符串 今天是一些C语言题目,最近天气炎热,多喝水。 NO.1 下面程序执行后&am…...
![](https://img-blog.csdnimg.cn/fd6f9a66fd79405693cc28752d297fa7.png)
Android签名查看
查看签名文件信息 第一种方法: 1.打开cmd,执行keytool -list -v -keystore xxx.keystore,效果如下图: 第二种方法: 1.打开cmd,执行 keytool -list -v -keystore xxxx.keystore -storepass 签名文件密码࿰…...
![](https://www.ngui.cc/images/no-images.jpg)
Educational Codeforces Round 3
目录 A. USB Flash Drives B. The Best Gift C. Load Balancing D. Gadgets for dollars and pounds A. USB Flash Drives #include<bits/stdc.h>using namespace std; const int N1e65; typedef long long ll; typedef pair<ll,ll> pll; typedef array<int…...
![](https://www.ngui.cc/images/no-images.jpg)
Docker Compose常用命令
常用命令 1.1 restart, start, stop-- 启动和停止服务 命令必须在 docker-compose.yml文件所在的目录下执行。 # 前台启动, 启动项目中的所有服务。 $. docker-compose up# 后台启动, 启动所有服务并在后台运行。 $. docker-compose up -d# 停止所有服务。 $. docker-compose …...
![](https://img-blog.csdnimg.cn/img_convert/6b9c8364a4bc349a291e98469ea343a0.png)
C++——智能指针
智能指针 文章目录 智能指针内存泄漏智能指针解决内存泄漏问题智能指针的使用及原理RAII智能指针对象的拷贝问题 C中的智能指针auto_ptrunique_ptrshared_ptrweak_ptr定制包装器C11和boost中智能指针的关系 内存泄漏 什么是内存泄漏:内存泄漏指因为疏忽或错误造成程…...
![](/images/no-images.jpg)
网站淘宝推广怎么做/百度账号人工客服电话
导读: 什么情况下需要使用全局上下文呢,情况有以下几点: 例如在Service服务中不能通过参数传过来,但是又需要用到这个context参数,这种情况下就需要使用全局上下文。例如工具类中,频繁传递上下文参数的话&a…...
![](/images/no-images.jpg)
如何做英文网站的外链/seo描述快速排名
常用的shell命令包括:ls(列出文件)、cd(切换目录)、mkdir(创建目录)、mv(移动或重命名文件)、rm(删除文件)、cat(显示文件内容)、echo(显示文本)、man(查看命令手册)等。...
![](/images/no-images.jpg)
wordpress 多标签/百度快速优化软件
JSON 语法规则 在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型: 对象表示为键值对 数据由逗号分隔 花括号保存对象 方括…...
网站建设销售中遇到的问题/百度左侧排名
本文作者为携程平台UED团队,同时感谢机票、度假、酒店UED团队协同搭建插画系统。对于每一个设计师来说,插画总是让人喜爱又烦恼。喜爱是因为插画具有特殊的表现力、丰富的图形语言、鲜明的个性特征,运用在设计中能让产品更具感染力并打动人心…...
![](/images/no-images.jpg)
贵阳建设网站公司/新疆今日头条新闻
生成0 - 1之间的随机数 select random();生成一个1 - 10000之间的随机整数 ceil:得到不小于参数的最小的整数 SELECT ceil(random()*(10000-1)1) as num;floor:得到不大于参数的最大整数 SELECT floor(random()*(10000-1)1) as num;trunc:截断…...
![](/images/no-images.jpg)
上海市建设安全协会网站特种工/b站推广网站入口mmm
zipinfo在不解压的情况下,获取zip压缩文件的的详细信息。zipinfo列出了ZIP档案中有关文件的技术信息,最常见的是在MS-DOS系统上。这些信息包括文件访问权限、加密状态、压缩类型、版本和操作系统或压缩程序的文件系统等。默认的行为(没有选项)是列出存档…...