22年38周

目录

一:有效的括号

二:删除字符串中的所有相邻重复项

三:逆波兰表达式求值

四:前 K 个高频元素(11111)


一:有效的括号

题目:有效的括号

思路:这道题是一个典型的用栈来处理的一道题,如果右括弧,直接入栈;左括弧,如果能遇到刚好匹配的则弹出栈顶的元素,如果没遇到则弹出。

import "fmt"
func isValid(s string) bool {
    bytes := []byte(s)
    stack := make([]byte ,0)
    stackIndex := 0
    kuoMap := make(map[byte]byte)
    
    kuoMap[')'] = '('
    kuoMap['}'] = '{'
    kuoMap[']'] = '['

    for _,v := range bytes {
        if stackIndex != 0 && kuoMap[v] == stack[stackIndex - 1] {
            stackIndex--
            stack[stackIndex] = ' '
            continue
        }
        //把切片的len和cap搞明白,cap只是说要不要进行扩容的一个标志
        //而len是具体stackIndex能不能访问的问题
        if stackIndex == len(stack) {
            stack = append(stack,v)
            stackIndex++
            continue
        }
        fmt.Println(stackIndex,"  ",len(stack),"  ",cap(stack))
        stack[stackIndex] = v
        stackIndex++
    }
    if stackIndex == 0 {
        return true
    }
    return false
}

二:删除字符串中的所有相邻重复项

题目:删除字符串中的所有相邻重复项

思路,这个有点像咱们的消消乐,也是利用栈来解题的这个思路。

func removeDuplicates(s string) string {
    stack := make([]byte,0)
    str := []byte(s)
    
    for _,v := range str {
        if len(stack) == 0 || stack[len(stack)-1] != v{
            stack = append(stack,v)
            continue
        }
        stack = stack[:len(stack)-1]
    }
    return string(stack)
}

三:逆波兰表达式求值

题目:逆波兰表达式求值

思路:逆波兰表达式求值也叫后缀表达式,计算思路就是遇到数字则压栈,遇到运算符则从栈顶弹出两个元素进行计算,之后把结果压栈,最后一个元素就是表达式的值。

import "strconv"

func evalRPN(tokens []string) int {
    stack := make([]int,0)

    for _,v := range tokens {
        if v == "+" {
            a := stack[len(stack)-1]
            b := stack[len(stack)-2]
            stack = stack[:len(stack)-2]
            stack = append(stack,a+b)
            continue
        }
        if v == "-" {
            a := stack[len(stack)-1]
            b := stack[len(stack)-2]
            stack = stack[:len(stack)-2]
            stack = append(stack,b-a)
            continue
        }
        if v == "*" {
            a := stack[len(stack)-1]
            b := stack[len(stack)-2]
            stack = stack[:len(stack)-2]
            stack = append(stack,a*b)
            continue
        }
        if v == "/" {
            a := stack[len(stack)-1]
            b := stack[len(stack)-2]
            stack = stack[:len(stack)-2]
            stack = append(stack,b/a)
            continue
        }
        num,_ := strconv.Atoi(v)
        stack = append(stack,num)
    }
    return stack[0]

}

四:前 K 个高频元素(11111)

题目:前 K 个高频元素

思路:

这道题是一个感觉比较有意思的题,有两个思路,三种写法。

思路一:利用堆这个数据结构,堆会自动保存前k个高频元素。如果用小顶堆就是找前k个高频元素,因为堆顶是整个堆最小的元素,如果遍历得知有比堆顶大的元素则把元素加入到堆中,之后重新构建堆。最终遍历完就能得到前k高频元素了。

写法一是自己的堆数据结构,所有操作都是自己来弄得。写法二是参考的别的写法,他用的是go语言自带的堆数据结构,可以好好读一读他的代码,能提升一下自己go语言基础,因为这里涉及到了接口等相关问题。

思路二:构造一个数据结构或者二维数组,其中第一个元素存key,第二存其出现的次数。利用sort对整个数组进行排序。

//思路一,写法一
func topKFrequent(nums []int, k int) []int {
    //利用堆,堆本身就是用来取前k个大数,或者前k个小数的
	//利用小顶堆,当堆的元素个数大于k的话,就把堆顶元素给弹出去
	heap := make([]int,0)
	hashTable := make(map[int]int)
	for _,v := range nums {
		hashTable[v]++
	}

	for key,_ := range hashTable {
		heapPush(&heap,k,key,hashTable)
	}
	return heap
   
}

//切片传值好好总结一下
func heapPush(heap *[]int,k,key int,hashTable map[int]int) {
	if len(*heap) < k {
		*heap = append(*heap,key)
	}else if hashTable[(*heap)[0]] < hashTable[key]{
		(*heap)[0] = key
	}else {
		return
	}

	//二叉树编号从1开始。开始更新堆
	for i:= len((*heap))/2;i>0;i-- {
		//三个数里面找个最小的
		min := hashTable[(*heap)[i-1]]
		if 2*i - 1 < len(*heap) && hashTable[(*heap)[2*i - 1]] < min {
			temp := (*heap)[i-1]
			(*heap)[i-1] = (*heap)[2*i - 1]
			(*heap)[2*i - 1] = temp

		}
		if 2*i < len(*heap) && hashTable[(*heap)[2*i]] < min {
			temp := (*heap)[i-1]
			(*heap)[i-1] = (*heap)[2*i]
			(*heap)[2*i] = temp
		}
	}

}
import "container/heap"
//思路一,写法二
func topKFrequent(nums []int, k int) []int {
    map_num:=map[int]int{}
    //记录每个元素出现的次数
    for _,item:=range nums{
        map_num[item]++
    }
    h:=&IHeap{}
    heap.Init(h)
    //所有元素入堆,堆的长度为k
    for key,value:=range map_num{
        heap.Push(h,[2]int{key,value})
        if h.Len()>k{
            heap.Pop(h)
        }
    }
    res:=make([]int,k)
    //按顺序返回堆中的元素
    for i:=0;i<k;i++{
        res[k-i-1]=heap.Pop(h).([2]int)[0]
    }
    return res
}

//构建小顶堆
type IHeap [][2]int

func (h IHeap) Len()int {
    return len(h)
}

func (h IHeap) Less (i,j int) bool {
    return h[i][1]<h[j][1]
}

func (h IHeap) Swap(i,j int) {
    h[i],h[j]=h[j],h[i]
}

func (h *IHeap) Push(x interface{}){
    *h=append(*h,x.([2]int))
}
func (h *IHeap) Pop() interface{}{
    old:=*h
    n:=len(old)
    x:=old[n-1]
    *h=old[0:n-1]
    return x
}

//思路二
import "sort"
func topKFrequent(nums []int, k int) []int {
    sortQueue := [][2]int{}
    hashTable := make(map[int]int)

    for _,v := range nums {
        hashTable[v]++
    }

    for k,v := range hashTable {
        sortQueue = append(sortQueue,[2]int{k,v})
    }
//利用go自带的排序功能进行排序
    sort.Slice(sortQueue,func (i,j int) bool {
        return sortQueue[i][1] > sortQueue[j][1]
    })
    res := make([]int,0)
    for i:=0;i<k;i++ {
        res = append(res,sortQueue[i][0])
    }
   return res
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值