golang刷题笔记

4 篇文章 1 订阅

2020/1/11

两数相加

主要是需要一个标志位对进位进行+1,不过走了点捷径,另外golang还是不太熟,目前没啥感觉。。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	headList := new(ListNode)
	head := headList
	num := 0
	fmt.Println(&l1,&l2,headList.Next,"xxxxxx!!!")
	for (l1 != nil || l2 != nil || num > 0) {
		headList.Next =  new(ListNode)
		headList = headList.Next
		if l1 != nil {
			num = num + l1.Val
			l1 = l1.Next
		}
		if l2 != nil {
			num = num + l2.Val
			l2 = l2.Next
		}
		headList.Val = (num) % 10
		num = num / 10
	}

	return head.Next
}

寻找两个正序数组的中位数

一般第一时间都会想到的暴力查找:

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
	nums1 = append(nums1,nums2...)
	sort.Ints(nums1)	// 合并数组排序
	n1 := len(nums1)
    if n1 == 1{
        return float64(nums1[0])
    }
	n2 := n1 / 2	// 拿到中位数索引
	flag := n1 % 2	// 判断奇偶标志位
	if flag == 0{	// 如果是偶数
		res := float64(nums1[n2]+nums1[n2-1]) / 2
		return res
	}else{  // 如果是奇数
        return float64(nums1[n2])
	}
}

但很显然对O(m+n)不成立,所以采用二分查找:

func findMedianSortedArrays(nums1 []int,nums2 []int) float64  {
	totalLength := len(nums1) + len(nums2)
	if totalLength % 2 == 1{	// 考虑奇数的情况下
		midIndex := totalLength / 2
		return float64(getKthElement(nums1,nums2,midIndex + 1))
	} else {	// 考虑偶数的情况下
		midIndex1, midIndex2 := totalLength / 2 - 1,totalLength / 2
		return float64(getKthElement(nums1,nums2,midIndex1 + 1) + getKthElement(nums1,nums2,midIndex2 + 1) ) / 2.0
		
	}
	
}

func getKthElement(nums1,nums2 []int,k int) int  {
	index1 , index2 := 0,0
	for  {
		if index1 == len(nums1) {
			return nums2[index2 + k - 1]
		}
		if index2 == len(nums2) {
			return nums1[index1 + k - 1]
		}

		if k == 1 {
			return min(nums1[index1],nums2[index2])
		}
		half := k / 2
		newIndex1 := min(index1 + half,len(nums1)) - 1
		newIndex2 := min(index2 + half,len(nums2)) - 1
		pivot1, pivot2 := nums1[newIndex1],nums2[newIndex2]
		if pivot1 <= pivot2 {
			k -= (newIndex1 - index1 + 1)
			index1 = newIndex1 + 1
		} else {
			k -= (newIndex2 - index2 + 1)
			index2 = newIndex2 + 1
		}
	}
	return 0
}

func min(x,y int) int  {
	if x < y {
		return x
	}
	return y
}

//func main()  {
//	var n = []int{1,2}
//	var m = []int{5,6}
//	fmt.Println(n,m)
//	cc := findMedianSortedArrays(n,m)
//	fmt.Println(cc)
//}

关于这题最快的方式是用折半二分,即我们只需要对第k / 2个数对位于两个数组的当前索引进行比较,如果nums1[k / 2] < nums2[ k / 2 ],那么就可以将nums1[k / 2]左边的数进行去除,那这其实是可以证明的。

A: 1 3 4 9
         ↑
B: 1 2 3 4 5 6 7 8 9

比如说上述官方的例子,显示的是4要比9小,那么4前的数据一定不存在中位数,我们只需要计算A、B中未参与比较的数字和是否>= 7,

n − ( k / 2 ∗ 2 − 1 ) > = n − k + 1 k − k / 2 ∗ 2 > = 0 k > = k / 2 ∗ 2 \begin{aligned} n-\left( k/2*2-1 \right) >&=n-k+1\\ k-k/2*2>&=0\\ k>&=k/2*2\\ \end{aligned} n(k/221)>kk/22>k>=nk+1=0=k/22

那么很显然:

  • 当k为偶数时, k > = k k>=k k>=k
  • 当k为奇数时, k > = k − 1 k>=k - 1 k>=k1

最长回文子串

这题可能是背会的。。。不过熟悉下用go来写:

func longestPalindrome(s string) string {
    if s == "" {
        return ""
    }
    start, end := 0, 0
    for i := 0; i < len(s); i++ {
        left1, right1 := expandAroundCenter(s, i, i)
        left2, right2 := expandAroundCenter(s, i, i + 1)
        if right1 - left1 > end - start {
            start, end = left1, right1
        }
        if right2 - left2 > end - start {
            start, end = left2, right2
        }
    }
    return s[start:end+1]
}

func expandAroundCenter(s string, left, right int) (int, int) {
    for ; left >= 0 && right < len(s) && s[left] == s[right]; left, right = left-1 , right+1 { }
    return left + 1, right - 1
}

2020/1/12

整数反转和回文串

func reverse(x int) int {
    y := 0
    for x!=0 {
        y = y*10 + x%10
        if !( -(1<<31) <= y && y <= (1<<31)-1) {
            return 0
        }
        x /= 10
    }
    return y
}

func isPalindrome(x int) bool {
	// 倒序后  判断是不是和原来的数字相等
	if x < 0 {
		return false
	}
	origin := x
	redirect := 0
	for x != 0 {
		redirect = redirect*10 + x%10
		x /= 10
	}
	return origin == redirect
}

这两题基本类似。

字符串转换整数 (atoi)

func myAtoi(str string) int {
	//去掉收尾空格
	str = strings.TrimSpace(str)
	result := 0
	sign := 1

	for i, v := range str {
		if v >= '0' && v <= '9' {
			result = result*10 + int(v-'0')
		} else if v == '-' && i == 0 {
			sign = -1
		} else if v == '+' && i == 0 {
			sign = 1
		} else {
			break
		}
       // 数值最大检测
		if result > math.MaxInt32 {
			if sign == -1 {
				return math.MinInt32
			}
			return math.MaxInt32
		}
	}

	return sign * result
}

2020/1/13

盛最多水的容器

func MaxArea(height []int) int {
	var (
		i, j = 0, len(height) - 1
		max  = 0
	)
	for j-i > 0 {
		if height[j] < height[i] {
			area := height[j] * (j - i)
			if max < area {
				max = area
			}
			j--
		} else {
			area := height[i] * (j - i)
			if max < area {
				max = area
			}
			i++
		}
	}

	return max
} 

最长公共前缀

func longestCommonPrefix(str []string) string {
    length := len(str)
	if length == 0 {
		return ""
	}
	// 目前已知的最长公用头 如果出现更短的,要及时变化
	var res = len(str[0])
	for l := 0; l < length-1; l++ {
		end := 0
		i := len(str[l+1])
		if i > res {
			i = res
		}
		for r := 0; r < i; r++ {
			if str[l][r] == str[l+1][r] {
				end ++
			} else {
				break
			}
		}
		if res >= end {
			res = end
		}
	}
	return str[0][0:res]
}

2020/1/14

有效的括号 and 合并两个有序链表

func isValid(s string) bool {
	var stack []byte
	var top int = -1
	for _, v := range s {
		if v == '(' {
			stack = append(stack, ')')
			top++
		}else if v == '[' {
			stack = append(stack, ']')
			top++
		}else if v == '{' {
			stack = append(stack, '}')
			top++
		}else{
			if top > -1 && byte(v) == stack[top] {
				stack = stack[:top]
				top--
			}else{
				return false
			}
		}
	}
	if len(stack) != 0 {
		return false
	}
	return  true
}

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	guard := &ListNode{}
	head := guard
	for {
		if l1 == nil {
			head.Next = l2
			break
		}
		if l2 == nil {
			head.Next = l1
			break
		}

		if l1.Val < l2.Val {
			head.Next = &ListNode{
				Val: l1.Val,
			}
			l1 = l1.Next
		} else {
			head.Next = &ListNode{
				Val: l2.Val,
			}
			l2 = l2.Next
		}
        head = head.Next
	}

	return guard.Next
}

2020/1/17

全排列

// 最终结果
var result [][]int

// 回溯核心
// nums: 原始列表
// pathNums: 路径上的数字
// used: 是否访问过
func backtrack(nums, pathNums []int, used[]bool) {
	// 结束条件:走完了,也就是路径上的数字总数等于原始列表总数
	if len(nums) == len(pathNums) {
		tmp := make([]int, len(nums))
		// 切片底层公用数据,所以要copy
		copy(tmp, pathNums)
		// 把本次结果追加到最终结果上
		result = append(result, tmp)
		return
	}

	// 开始遍历原始数组的每个数字
	for i:=0; i<len(nums); i++ {
		// 检查是否访问过
		if !used[i] {
			// 没有访问过就选择它,然后标记成已访问过的
			used[i] = true
			// 做选择:将这个数字加入到路径的尾部,这里用数组模拟链表
			pathNums = append(pathNums, nums[i])
			backtrack(nums,pathNums,used)
			// 撤销刚才的选择,也就是恢复操作
			pathNums = pathNums[:len(pathNums) -1]
			// 标记成未使用
			used[i] = false
		}
	}
}

func permute(nums []int) [][]int {
	var pathNums []int
	var used = make([]bool, len(nums))
    // 清空全局数组(leetcode多次执行全局变量不会消失)
    result = [][]int{}
	backtrack(nums, pathNums, used)
	return result
}

字符串相乘

**func multiply(num1 string,num2   string) string{
	var out_s = make([] int, len(num1)+len(num2))
	for i:=0; i<len(num1); i+=1{
		for j:=0 ; j < len(num2); j+=1{
			temp:= (num1[len(num1)-1-i] - '0')*(num2[len(num2)-1-j] - '0')
			out_s[i+j] += int(temp)
		}
	}
	for i := 0; i < len(out_s); i += 1{
		if out_s[i]>=10 {
			out_s[i+1], out_s[i] =  out_s[i+1]+out_s[i]/10, out_s[i]%10
		}
	}
	length :=0
	for i := 0; i<len(out_s) ; i+=1{
		if out_s[len(out_s)-1-i] != 0{
			length = len(out_s)-i
			break
		}
	}
	if length==0{
		return "0"
	}
	var out_string = ""
	for i:=0; i < length ; i+=1{
		out_string += strconv.Itoa(out_s[length-1-i])
	}

	return out_string
}

2020/1/18

螺旋矩阵

func spiralOrder(matrix [][]int) []int {
    if len(matrix) == 0 || len(matrix[0]) == 0 {
        return []int{}
    }
    var (
        rows, columns = len(matrix), len(matrix[0])
        order = make([]int, rows * columns)
        index = 0
        left, right, top, bottom = 0, columns - 1, 0, rows - 1
    )

    for left <= right && top <= bottom {
        for column := left; column <= right; column++ {
            order[index] = matrix[top][column]
            index++
        }
        for row := top + 1; row <= bottom; row++ {
            order[index] = matrix[row][right]
            index++
        }
        if left < right && top < bottom {
            for column := right - 1; column > left; column-- {
                order[index] = matrix[bottom][column]
                index++
            }
            for row := bottom; row > top; row-- {
                order[index] = matrix[row][left]
                index++
            }
        }
        left++
        right--
        top++
        bottom--
    }
    return order
}

2020/1/19

不同路径

func uniquePaths(m int, n int) int {
	if m == 1 || n == 1 {
		return 1
	}
	if m < n {
		//保证m是较大值
		m, n = n, m
	}
	dp := make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = 1
	}
	for i := 1; i < m; i++ {
		for j := 1; j < n; j++ {
			dp[j] += dp[j-1]
		}
	}
	return dp[n-1]
}

爬楼梯

func climbStairs(n int) int{
    arr := []int{1, 1}
    for i:=2; i<=n; i++{
        arr = append(arr, arr[i-1]+arr[i-2])
    }
    return arr[n]
}

2020/01/22

只出现一次的数字

func singleNumber(nums []int) int {
    eor := 0
    for i := 0;i<len(nums);i++{
        eor ^= nums[i]
    }
    return eor
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

submarineas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值