Leetcode(1)——数组、栈、队列

格式:

题号+题名+简单思路+code



T1: 两数之和

  • 不考虑去重,只找出第一个解;使用哈希表记录出现过的数字,O(N)时间复杂度
func twoSum(nums []int, target int) []int {
     
    if len(nums)==0 {
     
        return nil
    }
    tmp:=make(map[int]int,len(nums))
    for i,v := range nums {
     
        if j,ok:=tmp[target-v];ok {
     
            return []int{
     j,i}
        }
        tmp[v]=i
    }
    return nil
}
  • 哈希法能找出无序数组中所有和为定值的组合;但不能去重


※T560:和为K的子数组

  • 利用哈希字典找出所有和为K的子数组
  • 类似两数之和(两数之差),先转化成前缀和;前缀和用于处理数组区间问题
  • sum[j]-k=sum[i]
func subarraySum(nums []int, k int) int {
     
    memo:=make([]int,len(nums)+1)
    for i:=1;i<len(memo);i++ {
     
        memo[i]=memo[i-1]+nums[i-1]
    }
    count:=0
    dict:=make(map[int]int,0)
    for i:=0;i<len(memo);i++ {
         // 注意i从0开始
        if c,ok:=dict[memo[i]-k];ok {
     
            count+=c
        }
        dict[memo[i]]++
    }
    return count
}



剑指57:和为s的连续正数序列

  • 同样对于连续子数组和我们转化为前缀和数组
  • 可以使用哈希表,也可以因为前缀和是有序数组,使用滑动窗口

  • 哈希表
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        if target<=2:
            return []
        tmp=[i for i in range((target+1)//2+1)]
        pre=0
        for i in range(len(tmp)):
            tmp[i]=pre+tmp[i]
            pre=tmp[i]
        memo=dict()
        ans=[]
        for i in range(len(tmp)):
            if tmp[i]-target in memo:
                ans.append([j for j in range(memo[tmp[i]-target]+1, i+1)])
            memo[tmp[i]]=i
        return ans
  • 滑动窗口
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        if target<=2:
            return []
        tmp=[i for i in range((target+1)//2+1)]
        pre=0
        for i in range(len(tmp)):
            tmp[i]=pre+tmp[i]
            pre=tmp[i]
        i=0
        ans=[]
        for j in range(len(tmp)):
            if tmp[j]-tmp[i]<=target:
                pass
            else:
                while j>i and tmp[j]-tmp[i]>target:
                    i+=1
            if tmp[j]-tmp[i]==target:
                ans.append([k for k in range(i+1,j+1)])
        return ans



T15:三数之和

  • 考虑去重,所有解;使用排序+双指针;最坏情况为O(N^2)时间复杂度
import "sort"
func threeSum(nums []int) [][]int {
     
    target:=0
    ans:=[][]int{
     }
    sort.Ints(nums)
    for i:=0;i<len(nums)-2;i++ {
     
        if nums[i]>target {
     
            break
        }
        if i>0 && nums[i]==nums[i-1] {
     
            continue
        }
        lo:=i+1
        hi:=len(nums)-1
        a:=nums[i]
        for lo<hi && lo>=i+1 && hi<=len(nums)-1 {
     
            b:=nums[lo]
            c:=nums[hi]
            if a+b+c > target {
     
                hi--
            } else if a+b+c < target {
     
                lo++
            } else {
     
                ans=append(ans,[]int{
     a,b,c})
                for lo<hi && nums[hi-1]==nums[hi]{
     
                    hi--
                }
                for lo<hi && nums[lo+1]==nums[lo] {
     
                    lo++
                }
                lo++
                hi--
            }
        }
    }
    return ans
}
  • python3
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums=sorted(nums)
        ans=[]
        for i in range(len(nums)-2):
            if i>0 and nums[i]==nums[i-1]:
                continue
            x=nums[i]
            left=i+1
            right=len(nums)-1
            while left<right:
                if x+nums[left]+nums[right]>0:
                    while left<right and nums[right-1]==nums[right]:
                        right-=1
                    right-=1
                elif x+nums[left]+nums[right]<0:
                    while left<right and nums[left+1]==nums[left]:
                        left+=1
                    left+=1
                else:
                    ans.append([x, nums[left], nums[right]])
                    while left<right and nums[left+1]==nums[left]:
                        left+=1
                    left+=1
                    while left<right and nums[right-1]==nums[right]:
                        right-=1
                    right-=1
        return ans



T11:盛最多的水的容器

  • 双指针+短板效应;O(N)时间复杂度
func maxArea(height []int) int {
     
    n:=len(height)
    lo:=0
    hi:=n-1
    maxA:=0
    maxH:=0
    for lo<hi {
     
        if height[lo]<height[hi] {
     
            tmp:=(hi-lo)*height[lo]
            if tmp> maxA {
     
                maxA=tmp
            }
            maxH=height[lo]
            for lo<hi && height[lo+1]<=maxH {
     
                lo++
            }
            lo++
        } else {
     
            tmp:=(hi-lo)*height[hi]
            if tmp>maxA {
     
                maxA=tmp
            }
            maxH=height[hi]
            for lo<hi && height[hi-1]<=maxH {
     
                hi--
            }
            hi--
        }
    }
    return maxA
}



T16:最接近的三数之和

  • 由于计算的是和,所以无需考虑重复性;排序+双指针;O(N^2)时间复杂度
import "math"
import "sort"
func threeSumClosest(nums []int, target int) int {
     
    sort.Ints(nums)
    tmp:=math.Inf(0)
    var ans int
    for i:=0;i<len(nums)-2;i++ {
     
        if i>0 && nums[i]==nums[i-1] {
     
            continue
        }
        t:=nums[i]
        lo:=i+1
        hi:=len(nums)-1
        for lo<hi {
     
            currVal:=t+nums[lo]+nums[hi]-target
            c:=math.Abs(float64(currVal))
            if c<tmp {
     
                tmp=c
                ans=currVal+target
            }
            if currVal>0 {
     
                hi--
            } else if currVal<0 {
     
                lo++
            } else {
     
                return target
            }
        }
    }
    return ans
}




T739:每日温度

  • 单调栈(递减栈)
class Solution:
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        T.append(float("inf"))
        stack=[]
        ans=[0 for i in range(len(T))]
        for idx in range(len(T)):
            while len(stack)>0 and T[stack[-1]]<T[idx]:
                tmp=stack.pop()
                ans[tmp]=0 if idx==len(T)-1 else idx-tmp
            stack.append(idx)
        return ans[:-1]



func dailyTemperatures(T []int) []int {
     
    stack:=[]int{
     }
    ans:=make([]int, len(T))
    for i:=0;i<len(T);i++ {
     
        for len(stack)>0 && T[stack[len(stack)-1]]<T[i] {
     
            ans[stack[len(stack)-1]]=i-stack[len(stack)-1]
            stack=stack[:len(stack)-1]
        }
        stack=append(stack, i)
    }
    for i:=0;i<len(stack);i++ {
     
        ans[stack[i]]=0
    }
    return ans
}




※T316:去除重复字母

  • 维持一个单增栈
  • 出栈时需要保证相同字母在后续也会出现,对于stack中记录的字母就略过
func removeDuplicateLetters(s string) string {
     
    position:=[26]int{
     }
    memo:=[26]bool{
     }
    for i:=0;i<len(s);i++ {
     
        position[s[i]-'a']=i
    }
    stack:=[]byte{
     }
    for i:=0;i<len(s);i++ {
     
        if memo[s[i]-'a'] {
     
            continue
        }
        for len(stack)>0 && stack[len(stack)-1]>s[i] && position[stack[len(stack)-1]-'a']>i {
     
            x:=stack[len(stack)-1]
            stack=stack[:len(stack)-1]
            memo[x-'a']=false
        }
        stack=append(stack, s[i])
        memo[s[i]-'a']=true
    }
    return string(stack)
}




T84:柱状图中的最大矩形

  • 单调栈;适用于解决如找到第一个比其大/小这样的遍历问题;将O(N^2)→O(N)
  • 如单边的数矮个问题/升温天数T739和双边的T84
  1. 保证最后一个元素出栈
  2. 更新最值
  3. 双边扩展需要在栈中加辅助数-1 / re-index
  • 使用倒数第二个索引来明确正确左边界
func largestRectangleArea(heights []int) int {
     
    stack:=[]int{
     -1}
    maxA:=0
    for i:=0;i<len(heights);i++ {
     
        for stack[len(stack)-1]!=-1 && heights[stack[len(stack)-1]]>=heights[i] {
     
            x:=stack[len(stack)-1]
            stack=stack[:len(stack)-1]
            if (i-stack[len(stack)-1]-1)*heights[x]>maxA {
     
                maxA=(i-stack[len(stack)-1]-1)*heights[x]
            }
        }
        stack=append(stack, i)
    }
    for stack[len(stack)-1]!=-1 {
     
        x:=stack[len(stack)-1]
        stack=stack[:len(stack)-1]
        if (len(heights)-stack[len(stack)-1]-1)*heights[x]>maxA {
     
            maxA=(len(heights)-stack[len(stack)-1]-1)*heights[x]
        }
    }
    return maxA
}
  • re-index
type Stack []int

func (s *Stack) Push(i int) {
     
    *s=append(*s,i)
}

func (s *Stack) Pop() int {
     
    i:=(*s)[len(*s)-1]
    *s=(*s)[:len(*s)-1]
    return i
}

func (s Stack) Peek() int {
     
    return s[len(s)-1]
}

func largestRectangleArea(heights []int) int {
     
    flag:=-1
    maxVal:=0
    currIdx:=0
    heights=append(heights,flag)
    stack:=Stack{
     }
    for idx,val:=range heights {
     
        if len(stack)==0 || heights[stack.Peek()]<=val {
     
            stack.Push(idx)
        } else {
     
            for len(stack)>0 && heights[stack.Peek()]>val {
     
                currIdx=stack.Pop()
                tmp:=(idx-currIdx)*heights[currIdx]
                if tmp>maxVal {
     
                    maxVal=tmp
                }
            }
            stack.Push(currIdx)
            heights[currIdx]=val
        }

    }
    return maxVal
}




T85:最大矩形

  • 将该题看作m个柱状图最大矩形问题求全局最值
  • 单调栈的第一种写法,使用栈中倒数第二个索引来计算左边界
func maximalRectangle(matrix [][]byte) int {
     
    m:=len(matrix)
    if m==0 {
     
        return 0
    }
    n:=len(matrix[0])
    ans:=0
    memo:=make([]int,n)
    for i:=0;i<m;i++ {
     
        // 构成每一行的柱状图
        for j:=0;j<n;j++ {
     
            if matrix[i][j]=='1' {
     
                memo[j]++
            } else {
     
                memo[j]=0
            }
        }
        // 柱状图的最大面积
        stack:=make([]int,1)
        stack[0]=-1
        for j:=0;j<n;j++ {
     
            // 计算栈中倒数第二个元素的位置来代替re-index
            for stack[len(stack)-1]!=-1 && memo[stack[len(stack)-1]]>memo[j] {
     
                x:=stack[len(stack)-1]
                stack=stack[:len(stack)-1]
                if (j-stack[len(stack)-1]-1)*memo[x]>ans {
     
                    ans=(j-stack[len(stack)-1]-1)*memo[x]
                }
            }
            stack=append(stack,j)
        }
        // 保证出栈,注意最右端点
        for stack[len(stack)-1]!=-1 {
     
            x:=stack[len(stack)-1]
            stack=stack[:len(stack)-1]
            if (len(memo)-stack[len(stack)-1]-1)*memo[x]>ans {
     
                ans=(len(memo)-stack[len(stack)-1]-1)*memo[x]
            }
        }
    }
    return ans
}




※T986:区间列表交集

  • 双指针;最小区间右端点;O(M+N)时间复杂度
  • 同样的逻辑不能改成左端点
  • 类似归并排序最后的归并操作
func intervalIntersection(A [][]int, B [][]int) [][]int {
     
    point1:=0
    point2:=0
    ans:=[][]int{
     }
    for point1<len(A) && point2<len(B) {
     
        list1:=A[point1]
        list2:=B[point2]
        left:=max(list1[0], list2[0])
        if list1[1]<list2[1] {
     
            if list1[1]>=list2[0] {
     
                ans=append(ans, []int{
     left, list1[1]})
            }
            point1++
        } else {
     
            if list1[0]<=list2[1] {
     
                ans=append(ans, []int{
     left, list2[1]})
            }
            point2++
        }
    }
    return ans
}

func max(i int, j int) int {
     
    if i>j {
     
        return i
    } else {
     
        return j
    }
}




T56: 合并区间

  • 区间问题,先排序
  • 从相交区间中扩展min_startmax_end
import "sort"

func merge(intervals [][]int) [][]int {
     
    if len(intervals)==0 {
     
        return nil
    }
    ans:=[][]int{
     }
    sort.Slice(intervals, func(i int, j int) bool {
     
        return intervals[i][0]<intervals[j][0]
    })
    min_start:=intervals[0][0]
    max_end:=intervals[0][1]
    for i:=1;i<len(intervals);i++ {
     
        if intervals[i][0]<=max_end {
     
            if max_end<intervals[i][1] {
     
                max_end=intervals[i][1]
            }
        } else {
     
            ans=append(ans,[]int{
     min_start,max_end})
            min_start=intervals[i][0]
            max_end=intervals[i][1]
        }
    }
    ans=append(ans,[]int{
     min_start,max_end})
    return ans
}




※T239:滑动窗口的最大值

  • 使用单调队列的结构,保持窗口内降序,这样取最大值为O(1)
  • 存放的是索引值,首先将不在窗口内的删除,再删除窗口内小于当前值的所有值,最后插入当前值,并输出窗口中第一个值作为当前最大值
  • 平均时间复杂度为O(N)
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        ans=[]
        window=[]
        for i,num in enumerate(nums):
            while len(window)>0 and nums[window[-1]]<num:
                window.pop()
            window.append(i)
            if i>=k-1:
                ans.append(nums[window[0]])
                if window[0]==i-k+1:
                    window=window[1:]
        return ans



T717:1bit和2bit字符

  • 回溯法
func isOneBitCharacter(bits []int) bool {
     
    if len(bits)==0 {
     
        return false
    }
    if len(bits)<2 {
     
        return true
    }
    if bits[len(bits)-2]==1 {
     
        return !isOneBitCharacterAssist(bits, len(bits)-3)
    }
    return true
}

func isOneBitCharacterAssist(bits []int, index int) bool {
     
    if index==-1 {
     
        return true
    }
    if bits[index]==0 {
     
        if isOneBitCharacterAssist(bits, index-1) {
     
            return true
        }
        if index>0 && bits[index-1]==1 {
     
            if isOneBitCharacterAssist(bits, index-2) {
     
                return true
            }
        }
    } else if index>0 && bits[index]==1 && bits[index-1]==1 {
     
        if isOneBitCharacterAssist(bits, index-2) {
     
            return true
        }
    } else {
     
        return false
    }
    return false
}
  • 数学法
func isOneBitCharacter(bits []int) bool {
     
    step:=0
    for i:=0;i<len(bits);i+=step {
     
        if bits[i]==1 {
     
            step=2
        } else {
     
            step=1
        }
    }
    return step==1
}



T832:翻转图像

  • O(MN)时间复杂度
func flipAndInvertImage(A [][]int) [][]int {
     
    for i:=0;i<len(A);i++ {
     
        tmp:=A[i]
        for lo,hi:=0,len(tmp)-1;lo<=hi;lo,hi=lo+1,hi-1 {
     
            if lo==hi {
     
                tmp[lo]=1-tmp[lo]
                continue
            }
            if tmp[lo]!=tmp[hi] {
     
                continue
            } else {
     
                tmp[lo]=1-tmp[lo]
                tmp[hi]=1-tmp[hi]
            }
        }
    }
    return A
}



T232:用栈实现队列

  • 使用两个栈(两次反序)来达到正序
class MyQueue:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.stack1=[]
        self.stack2=[]


    def push(self, x: int) -> None:
        """
        Push element x to the back of queue.
        """
        self.stack2.append(x)


    def pop(self) -> int:
        """
        Removes the element from in front of queue and returns that element.
        """
        if len(self.stack1)==0:
            while len(self.stack2)>0:
                self.stack1.append(self.stack2.pop())
        if len(self.stack1)>0:
            return self.stack1.pop()
        return -1


    def peek(self) -> int:
        """
        Get the front element.
        """
        if len(self.stack1)==0:
            while len(self.stack2)>0:
                self.stack1.append(self.stack2.pop())
        if len(self.stack1)>0:
            return self.stack1[-1]
        return -1


    def empty(self) -> bool:
        """
        Returns whether the queue is empty.
        """
        return len(self.stack1)==0 and len(self.stack2)==0



# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()



T225:用队列实现栈

  • 两个队列,使用O(N)时间复杂度互相转移实现反序
    Leetcode(1)——数组、栈、队列_第1张图片
type MyStack struct {
     
    q1 []int
    q2 []int
    item int
    length int
}


/** Initialize your data structure here. */
func Constructor() MyStack {
     
    return MyStack{
     []int{
     }, []int{
     }, -1, 0}
}


/** Push element x onto stack. */
func (this *MyStack) Push(x int)  {
     
    if len(this.q1)==0 {
     
        this.q1=append(this.q1, x)
        for idx:=0;idx<this.length;idx++ {
     
            x:=this.q2[0]
            this.q1=append(this.q1, x)
            this.q2=this.q2[1:]
        }
    } else if len(this.q2)==0 {
     
        this.q2=append(this.q2, x)
        for idx:=0;idx<this.length;idx++ {
     
            x:=this.q1[0]
            this.q2=append(this.q2, x)
            this.q1=this.q1[1:]
        }
    }
    this.item=x
    this.length++
}


/** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
     
    var rVal int
    if len(this.q1)==0 {
     
        rVal=this.q2[0]
        this.q2=this.q2[1:]
        if len(this.q2)>0 {
     
            this.item=this.q2[0]
        }
    } else if len(this.q2)==0 {
     
        rVal=this.q1[0]
        this.q1=this.q1[1:]
        if len(this.q1)>0 {
     
            this.item=this.q1[0]
        }
    }
    this.length--
    return rVal
}


/** Get the top element. */
func (this *MyStack) Top() int {
     
    return this.item
}


/** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
     
    return this.length==0
}


/**
 * Your MyStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * param_2 := obj.Pop();
 * param_3 := obj.Top();
 * param_4 := obj.Empty();
 */
  • 用一个队列,通过O(N)时间复杂度,类似插入排序实现反序
type MyStack struct {
     
    q1 []int
}


/** Initialize your data structure here. */
func Constructor() MyStack {
     
    return MyStack{
     []int{
     }}
}


/** Push element x onto stack. */
func (this *MyStack) Push(x int)  {
     
    this.q1=append(this.q1, x)
    idx:=len(this.q1)-1
    for idx>0 {
     
        this.q1[idx], this.q1[idx-1]=this.q1[idx-1], this.q1[idx]
        idx--
    }
}


/** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
     
    x:=this.q1[0]
    this.q1=this.q1[1:]
    return x
}


/** Get the top element. */
func (this *MyStack) Top() int {
     
    return this.q1[0]
}


/** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
     
    return len(this.q1)==0
}


/**
 * Your MyStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * param_2 := obj.Pop();
 * param_3 := obj.Top();
 * param_4 := obj.Empty();
 */



T20:有效的括号

  • 括号问题→栈
var memo map[byte]byte = map[byte]byte{
     ')':'(', '}':'{', ']':'['}

func isValid(s string) bool {
     
    stack:=[]byte{
     }
    for i:=0;i<len(s);i++ {
     
        if b, ok:=memo[s[i]];ok {
     
            if len(stack)==0 || stack[len(stack)-1]!=b {
     
                return false
            }
            stack=stack[:len(stack)-1]
        } else {
     
            stack=append(stack, s[i])
        }
    }
    if len(stack)>0 {
     
        return false
    }
    return true
}



T42:接雨水

  • s u m = s u m + min ⁡ { m a x H [ 0 : i ] , m a x H [ i : n − 1 ] } − H [ i ] sum=sum+\min\{maxH_{[0:i]},maxH_{[i:n-1]}\}-H[i] sum=sum+min{ maxH[0:i],maxH[i:n1]}H[i]

  • 记忆化递归;O(N)时间复杂度;O(N)空间复杂度

func trap(height []int) int {
     
    memoL:=make([]int,len(height))
    for i:=0;i<len(memoL);i++ {
     
        memoL[i]=-1
    }
    memoR:=make([]int,len(height))
    for i:=0;i<len(memoR);i++ {
     
        memoR[i]=-1
    }
    sum:=0
    for i:=0;i<len(height);i++ {
     
        i1:=getMaxL(height, i, memoL)
        i2:=getMaxR(height, i, memoR)
        if i1>i2 {
     
            sum+=i2-height[i]
        } else {
     
            sum+=i1-height[i]
        }
    }
    return sum
}

func getMaxL(height []int, loc int, memoL []int) int {
     
    if loc==0 {
     
        memoL[0]=height[0]
        return height[0]
    }
    if memoL[loc]!=-1 {
     
        return memoL[loc]
    }
    tmp:=getMaxL(height, loc-1, memoL)
    if tmp>height[loc] {
     
        memoL[loc]=tmp
        return tmp
    } else {
     
        memoL[loc]=height[loc]
        return height[loc]
    }
}
func getMaxR(height []int, loc int, memoR []int) int {
     
    if loc==len(height)-1 {
     
        memoR[loc]=height[loc]
        return height[loc]
    }
    if memoR[loc]!=-1 {
     
        return memoR[loc]
    }
    tmp:=getMaxR(height, loc+1, memoR)
    if tmp>height[loc] {
     
        memoR[loc]=tmp
        return tmp
    } else {
     
        memoR[loc]=height[loc]
        return height[loc]
    }
}
  • s u m = s u m + min ⁡ { m a x H [ 0 : l o ] , m a x H [ h i : n − 1 ] } − H [ i ∈ { l o , h i } ] sum=sum+\min\{maxH_{[0:lo]},maxH_{[hi:n-1]}\}-H[i\in\{lo,hi\}] sum=sum+min{ maxH[0:lo],maxH[hi:n1]}H[i{ lo,hi}]
  • 短板效应
  • O(N)时间复杂度;O(1)空间复杂度
func trap(height []int) int {
     
    if len(height)==0 {
     
        return 0
    }
    ans:=0
    left:=height[0]
    right:=height[len(height)-1]
    point1:=0
    point2:=len(height)-1
    for point1<point2 {
     
        if left<right {
     
            if height[point1+1]<=left {
     
                ans+=left-height[point1+1]
            } else {
     
                left=height[point1+1]
            }
            point1++
        } else {
     
            if height[point2-1]<=right {
     
                ans+=right-height[point2-1]
            } else {
     
                right=height[point2-1]
            }
            point2--
        }
    }
    return ans
}



※T224:基本计算器

  • 利用栈存储之前的计算结果
  • + , − , ∗ , / , ( , ) +, -, *, /, (, ) +,,,/,(,)
import "unicode"

func calculate(s string) int {
     
    seq:=[]rune(s)
    idx:=0
    return calculateAssist(seq, &idx)
}

func calculateAssist(seq []rune, idx *int) int {
     
    num:=0
    sign:='+'
    ans:=0
    stack:=[]int{
     }
    for *idx<len(seq) {
     
        c:=seq[*idx]
        if unicode.IsNumber(c) {
     
            num=num*10+int(c-'0')
        } else if c=='(' {
     
            (*idx)++
            num=calculateAssist(seq, idx)
        } else if !unicode.IsSpace(c) {
         // 运算符或者')'或者'.'
            if c==')' {
     
                break
            }
            switch sign {
     
                case '+':
                    stack=append(stack, num)
                case '-':
                    stack=append(stack, -num)
                case '*':
                    stack[len(stack)-1]*=num
                case '/':
                    stack[len(stack)-1]/=num
            }
            sign=c
            num=0
        }
        (*idx)++
    }
    switch sign {
         // 末尾数字
        case '+':
            stack=append(stack, num)
        case '-':
            stack=append(stack, -num)
        case '*':
            stack[len(stack)-1]*=num
        case '/':
            stack[len(stack)-1]/=num
    }
    for i:=0;i<len(stack);i++ {
     
        ans+=stack[i]
    }
    return ans
}



T394:字符串解码

  • 十分类似于基本计算器的思路,即对括号的处理上
import "unicode"
import "bytes"

func decodeString(s string) string {
     
    seq:=[]rune(s)
    idx:=0
    return decodeStringAssist(seq, &idx)
}

func decodeStringAssist(seq []rune, idx *int) string {
     
    var tmp bytes.Buffer
    num:=0
    for *idx < len(seq) {
     
        c:=seq[*idx]
        if unicode.IsNumber(c) {
         // 数字
            num=num*10+int(c-'0')
        } else if unicode.IsLetter(c) {
         // 字母
            tmp.WriteRune(c)
        } else if c=='[' {
         // '['代替了括号和乘法
            *(idx)++
            ans:=decodeStringAssist(seq, idx)
            for i:=0;i<num;i++ {
     
                tmp.WriteString(ans)
            }
            num=0
        } else {
         // ']'表示终止
            break
        }
        *(idx)++
    }
    return tmp.String()
}



剑指04:二维数组中的查找

  • 相当于构造一棵二叉搜索树
func findNumberIn2DArray(matrix [][]int, target int) bool {
     
    i:=len(matrix)-1
    j:=0
    for i>=0 && j<len(matrix[0]) {
     
        if matrix[i][j]<target {
     
            j++
        } else if matrix[i][j]>target {
     
            i--
        } else {
     
            return true
        }
    }
    return false
}



※剑指45:把数组排成最小的数

  • 排序判断:任意交换相邻两个元素的位置都会使结果增大
  • 解决 3、32、34的顺序
func minNumber(nums []int) string {
     
    str_nums:=make([]string, len(nums))
    for i:=0;i<len(nums);i++ {
     
        str_nums[i]=strconv.Itoa(nums[i])
    }
    sort.Slice(str_nums, func(i int, j int) bool {
     
        return str_nums[i]+str_nums[j]<=str_nums[j]+str_nums[i]
    })
    return strings.Join(str_nums, "")
}



※剑指31:判断栈的压入序列、弹出序列

class Solution:
    def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
        stack, i = [], 0
        for num in pushed:
            stack.append(num) # num 入栈
            while stack and stack[-1] == popped[i]: # 循环判断与出栈
                stack.pop()
                i += 1
        return not stack
func validateStackSequences(pushed []int, popped []int) bool {
     
    stack:=[]int{
     }
    index:=0
    for i:=0;i<len(pushed);i++ {
     
        stack=append(stack, pushed[i])
        for len(stack)>0 && stack[len(stack)-1]==popped[index] {
     
            stack=stack[:len(stack)-1]
            index++
        }
    }
    if len(stack)==0 {
     
        return true
    }
    return false
}



※剑指51:数组中的逆序对

  • 基于归并排序思想
  • 在对数组进行归并排序的过程中,将无序变为有序的过程即可统计逆序对
func reversePairs(nums []int) int {
     
    tmp:=make([]int, len(nums))
    return mergeSort(nums, tmp, 0, len(nums)-1)
}

func mergeSort(nums []int, tmp []int, lo int, hi int) int {
     
    if lo>=hi {
     
        return 0
    }
    mid:=(hi-lo)/2+lo
    num1:=mergeSort(nums, tmp, lo, mid)
    num2:=mergeSort(nums, tmp, mid+1, hi)
    if nums[mid]<=nums[mid+1] {
         // 此时已有序
        return num1+num2
    }
    count:=0
    for i:=lo;i<=hi;i++ {
     
        tmp[i]=nums[i]
    }
    i:=lo
    j:=mid+1
    for k:=lo;k<=hi;k++ {
     
        if i==mid+1 {
     
            nums[k]=tmp[j]
            j++
        } else if j==hi+1 {
     
            nums[k]=tmp[i]
            i++
        } else {
     
            if tmp[i]<=tmp[j] {
         // 稳定排序
                nums[k]=tmp[i]
                i++
            } else {
     
                nums[k]=tmp[j]
                j++
                count+=mid-i+1
            }
        }
    }
    return num1+num2+count
}

你可能感兴趣的:(leetcode,leetcode)