基本全用切片不用数组
var n []T
n := make([]T,0)
n := []T{}
append
s1 := make([]int,2,4)
s1 = append(s1,1)
s1 = append(s1,1,2)
s2 := make([]int,0,4)
s2 = append(s2, s1...) /将s1全部追加给说s2
s2 = append(s2, s1[0:2]...) /注意s1[0:2]仍然是个切片
拷贝操作:copy
(必须声明需要拷贝的数组长度)
dst := make([]int,len(src))
copy(dst,src)
copy(dst[1:],src)
删除操作:src[a:b]
【左闭右开)
遍历数组:forr fori
s := []int{}
for index, v := range s {}
for i := 0; i < len(s); i++ {}
sort
包操作:
import "sort" 升序
/排序
sort.Ints(x []int)
sort.Float64s(x []float64)
sort.Strings(x []string)
/ 自定义排序
sort.Slice(src,func(i, j int) bool{
return src[i] > src[j] 逆序
})
/ 二分查找:
1. 返回x在a中的最小下标!
2. 如果x中不存在a,则返回a在x中应该存在的位置
eg:[1,3] 中查找2则返回1;查找4则返回2(可能返回n)
index: 0 1
func SearchInts(a []int, x int) int {}
func SearchFloat64s(a []float64, x float64) int {}
func SearchStrings(a []string, x string) int {}
<
升序 、 >
降序)要遍历和其他每个元素进行比较:
两数之和:Hash、最长无重复:队列…【因为都含有contains()方法】
需要去重:HashSet和HashMap
声明
var n [][]T
n := make([][]T,0)
n := [][]T{}
DFS求矩阵中相邻1的最大和:
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int maxSum = 0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j] == 1){
maxSum = Math.max(maxSum,dfs(grid,i,j));
}
}
}
return maxSum;
}
//递归 推荐
public static int dfs(int[][] grid,int i,int j){
if(i < 0 || j< 0 || i>=grid.length || j>=grid[0].length || grid[i][j] == 0){
return 0;
}
grid[i][j] = 0;
return 1+dfs(grid,i+1,j)+dfs(grid,i,j+1)+dfs(grid,i-1,j)+dfs(grid,i,j-1);
}
// 栈
public static int sumIndex(int[][] grid,int x,int y){
if(grid[x][y] == 0) return 0;
Deque<Integer> stacki = new ArrayDeque<>();
Deque<Integer> stackj = new ArrayDeque<>();
stacki.push(x);
stackj.push(y);
grid[x][y] = 0;
int ans = 0;
while(!stacki.isEmpty()){
int i = stacki.pop();
int j = stackj.pop();
ans++;
if(i+1 < grid.length && grid[i+1][j] == 1){
stacki.push(i+1);
stackj.push(j);
grid[i+1][j] = 0;
}
if(j+1 < grid[0].length && grid[i][j+1] == 1){
stacki.push(i);
stackj.push(j+1);
grid[i][j+1] = 0;
}
if(i-1 > -1 && grid[i-1][j] == 1){
stacki.push(i-1);
stackj.push(j);
grid[i-1][j] = 0;
}
if(j-1 > -1 && grid[i][j-1] == 1){
stacki.push(i);
stackj.push(j-1);
grid[i][j-1] = 0;
}
}
return ans;
}
}
算法常常以这种方式出链表:
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
Go中的链表list
:和sync.Map{}一样支持所有数据类型
l := &list.List{}
l.Len()
f := l.Front()
b := l.Back()
for i := ll.Front(); i != nil; i = i.Next() {
fmt.Println(i.Value)
}
fast.Next
for fast.Next != nil {
fast = fast.Next.Next
if fast == nil {
break
}
slow = slow.Next
}
算法实现LRU:map + 双向链表
入环点: 其实是道数学问题:2(a+b) = a+b+n(c+b) ==> a=(n-1)(c+b)+c
(快指针已经走了n圈)
两链相交点: 也是一道数学问题 我走了你走过的路,你走了我走过的路,然后我们就相遇了
(不相遇的时候最终也会想等 只不过相等值为nil
)
基本操作
s := "abcd123你哈"
len(s) // 字节数
for i := 0; i < len(s); i++ {
fmt.Println(s[i]) //字节
}
for index, c := range s {
fmt.Println(index,c) //字符
}
b := []byte(s) //转换为字节切片
r := []rune(s) //转换为字符切片
strings
包:https://studygolang.com/static/pkgdoc/pkg/strings.htm
strconv
包:
// string ===> int
atoi, err := strconv.Atoi(s)
// int ===> string
itoa := strconv.Itoa(123)
一维数组: int dp = array[0];
二维数组: int[] pd = new int[array[0].length+1];
① 只能向右或向下
② 左上角到右下角路径问题
还有一种方法就是不创建新数组,直接修改二维数组中的值。
思路: 先计算出第一行与第一列,然后从(1,1)点开始 Math.min/max......
注意⚠️: 返回所有可能的确切值:回溯算法;返回所有可能的数量:动态规划!
list.add(0,node.val);//每次加到0的位置,就自动逆序了
func diameterOfBinaryTree(root *TreeNode) int {
// 全局遍历作为最终结果
var res int
// 求数深度函数
var depth func(*TreeNode) int
depth = func(node *TreeNode) int {
......
/ 递归求左右子树的深度
leftDepth := depth(node.Left)
rightDepth := depth(node.Right)
......
将root + left + right 作为更新最终结果res的一种情况
......
/ 而只将 root+left 和 root+right作为返回的结果
return max(leftPath,rightPath)+1
}
depth(root)
return res
}
分治算法能解决的问题,一般需要满足下面这几个条件:
回想归并排序的merge函数就可以
分治算法一般都比较适合用递归来实现:
代码顺序:终止条件==>递的过程==>归的过程
DFS(栈 / 递归)
递归:往往递归简单一点 始终记住:重复递归的假设已经存在,只考虑①第一步和第二步怎么写,以及②递归结束标志!!!
栈:一定在入栈(队)后立即标记
Deque<Integer> stack = new ArrayDeque<>();
stack.push(start);
stack.pop();
stack.peek();//返回但不弹出
BFS(队)
需要多源广度搜索,只需要把最初出的多个源点一起入队(leecode 994)
Queue<Integer> queue = new LinkedList<>();
queue.add(start);
queue.poll();
queue.peek();//返回但不弹出
相同与区别:DFS节点周围的都入栈,取栈顶元素;BFS节点周围的都入队,出队头元素。
当出现点与点有向关联:画图 ⇒ 拓扑排序 【map存节点+入度】
func canFinish(numCourses int, prerequisites [][]int) bool {
/ topo[节点]入度
topo := make(map[int]int,numCourses)
。。。
/ 入度为0的节点存入stack
stack := []int{}
for i:=0;i<numCourses;i++ {
if topo[i] == 0 {
stack = append(stack,i)
}
}
count := 0 / 也可以是[]res 返回拓扑过程
for len(stack) > 0 {
// 取出入度为0的节点
zeroIndegree := stack[len(stack)-1]
stack = stack[:len(stack)-1]
count++
// 将0度节点所指向的节点的入度减1
for _,v := range prerequisites {
if v[1] == zeroIndegree {
topo[v[0]]--
/ 注意 :直接在这里再获取入度为0的点
if topo[v[0]] == 0 {
stack = append(stack,v[0])
}
}
}
}
return count == numCourses
}
map[keyType]valueType)
var 变量名 map[keyType]valueType
(不会分配数据内存,是nil
)
map[keyType]valueType{k1:v1,k2:v2}
make(map[keyType]valueType)
不存在会返回默认值:
m := make(map[string]int)
m["id"] = 2001
fmt.Println(m["id"]) /2001
fmt.Println(m["name"]) /0
但其实获取元素时会将是否存在作为第二个元素返回:
v,ok := m["name"]
if ok {
fmt.Println(v)
}else {
fmt.Println("不存在")
}
delete(map,键)
因为map是没有下标的,所以只能是 forr:(当然,散列表坑定是无序输出)
mm := map[string]int{"id":1,"name":2001,"age":520}
for k, v := range mm {
fmt.Println(k,v)
}
math
包import "math"
绝对值:func Abs(x float64) float64
次方值:func Pow(x, y float64) float64 取根号2:fmt.Print(math.Pow(16,0.5))
最大值:func Max(x, y float64) float64
最小值:func Min(x, y float64) float64
平方根:math.Sqrt(32)
立方根:math.Cbrt(27)
向下取整:func Floor(x float64) float64
向上取整:func Ceil(x float64) float64
最大整数:MaxInt64
最小整数:MinInt64
fmt.Scan(&n)
只能往读入基本数据类型import "fmt"
var n int
var s string
num, _ := fmt.Scan(&n, &s)
if num == 0 {
fmt.Println("没有元素")
}else {
fmt.Println("输入元素:",n,s)
}
m,n = n,m
mid := (right + left) >> 1
,
tt := &t{
a:2,
b:3,
}
res := []int{
3,
}
10e3
:10
*10
32
31:1<<31
n&1
== 1 ;偶数:n&1
== 0