leedocde实战最新

1 二数之和(龙云2020-10-11)

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解:
第一种方式暴力破解法 (时间复杂度01)

func twoSum(nums []int, target int) []int {
//计算出数组的长度
len := len(nums)
for i:=0;i<len - 1;i++{
for j:= i + 1;j<len;j++{
if nums[i] + nums[j] == target{
return []int{i,j}
}
}
}
return []int{}
}

第二种方式(时间复杂度o(n)),通过hash表的方式
func twoSum(nums []int, target int) []int {
mapArray := make(map[int]int)
//1 定义一个map数组
//2 每次用目标值-当前的这个值看看是否在map中
for i:=0;i<len(nums);i++{
v := nums[i];
if k,ok := mapArray[target - v];ok{
return []int{k,i}
}
mapArray[v] = i;
}
return []int{}
}

或者用这种方式

func twoSum(nums []int, target int) []int {
mapArray := make(map[int]int)
//1 定义一个map数组
//2 每次用目标值-当前的这个值看看是否在map中
for i,v := range nums{
if k,ok := mapArray[target - v];ok{
return []int{k,i}
}
mapArray[v] = i;
}
return []int{}

}

2 三数之和(伟江2020-10-11)

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组

示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

package solution
import (
“sort”
“strconv”
)
// 核心思想(不排序):
// 1. 在第一层循环,从头开始遍历元素,相同的元素,跳过
// 2. 在第二层循环,记录前两次比较的大小
// 3. 在第三层循环,判断三个数的和是否为0
// 4. 对三个元素从小到大,依次插入切片中
// 5. 判断切片是否在目标切片中,采用map[string]bool{}来记录存在的切片(注意:这里使用relect来判断切片是否相等会导致time limit exceeded)
// 时间复杂度:O(n^3) 空间复杂度: O(n1) n1为结果的切片长度
func ThreeSum(nums []int) [][]int {
isSearch := map[int]bool{}
isVisited := map[string]bool{}
res := [][]int{}
for i := 0; i < len(nums); i++ {
if _, ok := isSearch[nums[i]]; ok {
continue
}
for j := i + 1; j < len(nums); j++ {
maxNum := nums[j]
minNum := nums[i]
if nums[j] < nums[i] {
maxNum = nums[i]
minNum = nums[j]
}
tmpArr := []int{}
sum := nums[i] + nums[j]
for k := j + 1; k < len(nums); k++ {
if sum+nums[k] == 0 {
tmpStr := “”
if nums[k] > maxNum {
// nums[k] > maxNum > minNum
tmpArr = append(tmpArr, minNum, maxNum, nums[k])
tmpStr += strconv.Itoa(minNum) + strconv.Itoa(maxNum) + strconv.Itoa(nums[k])
} else if nums[k] > minNum {
// maxNum > nums[k] > minNum
tmpArr = append(tmpArr, minNum, nums[k], maxNum)
tmpStr += strconv.Itoa(minNum) + strconv.Itoa(nums[k]) + strconv.Itoa(maxNum)
} else {
// maxNum > minNum > nums[k]
tmpArr = append(tmpArr, nums[k], minNum, maxNum)
tmpStr += strconv.Itoa(nums[k]) + strconv.Itoa(minNum) + strconv.Itoa(maxNum)
}
if _, ok := isVisited[tmpStr]; !ok {
res = append(res, tmpArr)
isVisited[tmpStr] = true
}
break
}
}
}
isSearch[nums[i]] = true
}
return res
}

package main
import (
“fmt”
“os”
“sort”
“strconv”
)
func main(){
nums := []int{-1, 0, 1, 2, -1, -4}
res := ThreeSumOpt(nums)
fmt.Println(res)
}
// 核心思想(排序):
// 1. 先对数组进行排序
// 2. 在第一层循环中,从头开始遍历元素,相同的元素,跳过
// 3. 在第二层循环中,只要j(j=i+1)<k(k=len-1),当三个数之和小于0,j++;当三个数之和大于0,k–;当三个数之和等于0,j++,k–,并且记录三个数;
// 注意点:判断切片是否在目标切片中,采用map[string]bool{}来记录存在的切片(注意:这里使用relect来判断切片是否相等会导致time limit exceeded)
// 时间复杂度:O(n^2) 空间复杂度: O(n1) n1为结果的切片长度
func ThreeSumOpt(nums []int) [][]int {
sort.Ints(nums)
isSearch := map[int]bool{}
isVisited := map[string]bool{}
res := [][]int{}
for i := 0; i < len(nums); i++ {
if _, ok := isSearch[nums[i]]; ok {
continue
}
j := i + 1
k := len(nums) - 1
for {
if j >= k {
break
}
tmpArr := []int{}
if nums[i]+nums[j]+nums[k] < 0 {
j++
} else if nums[i]+nums[j]+nums[k] > 0 {
k–
} else {
tmpArr = append(tmpArr, nums[i], nums[j], nums[k])
tmpStr := strconv.Itoa(nums[i]) + strconv.Itoa(nums[j]) + strconv.Itoa(nums[k])
if _, ok := isVisited[tmpStr]; !ok {
res = append(res, tmpArr)
isVisited[tmpStr] = true
}
j++
k–
}
}
isSearch[nums[i]] = true
}
fmt.Println(isSearch)
return res
}

3 两数相加(燕伟 2020-10-18)

https://leetcode-cn.com/problems/add-two-numbers/
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
main.go
package main
import (
“fmt”
“src”
)
func main() {
l1 := new(src.ListNode)
l2 := new(src.ListNode)
temp1 := l1
temp2 := l2
num1 := []int{2, 4, 3}
num2 := []int{5, 6, 4}
for i := 0; i < len(num1); i++ {
temp1.Val = num1[i]
fmt.Println(“wel com”)
if i == len(num1)-1 {
break
}
temp1.Next = new(src.ListNode)
temp1 = temp1.Next
}
for i := 0; i < len(num2); i++ {
temp2.Val = num2[i]
if i == len(num2)-1 {
break
}
temp2.Next = new(src.ListNode)
temp2 = temp2.Next
}
l3 := src.AddTwoNumbers(l1,l2)
fmt.Println(l3.GetInt())
}

sum.go
package src
type ListNode struct {
Val int
Next *ListNode
}
func AddTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
//list := &ListNode{0, nil}
list := new(ListNode)
//这里用一个result,只是为了后面返回节点方便,并无他用
result := list
tmp := 0
for l1 != nil || l2 != nil || tmp != 0 {
if l1 != nil {
tmp += l1.Val
l1 = l1.Next
}
if l2 != nil {
tmp += l2.Val
l2 = l2.Next
}
list.Next = &ListNode{tmp % 10, nil}
tmp = tmp / 10
list = list.Next
}
return result.Next
}
func (l *ListNode) GetInt() []int {
if l == nil {
return []int{}
}
nums := []int{}
for l != nil {
nums = append(nums, l.Val)
l = l.Next
}
return nums
}

4 有效的字母异位词(王宇 2020-10-18)

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:

输入: s = “rat”, t = “car”
输出: false

func isAnagram1(s string, t string) bool {
var sTmpMap = make(map[rune]int)
var tTmpMap = make(map[rune]int)
for _, c := range s {
sTmpMap[c] = sTmpMap[c] + 1
}
for _, c := range t {
sTmpMap[c] = tTmpMap[c] + 1
}
return reflect.DeepEqual(sMap, tMap)
}

第二种解法
package main
import (
“fmt”
)
func main(){
s1 := “hello”
s2 := “hello”
res := isAnagram1(s1,s2)
fmt.Println(res)
}
func isAnagram(s1 string,s2 string) bool {
func isAnagram(s string, t string) bool {
len1 := len(s)
len2 := len(t)
if len1 != len2 {
return false
}
shus1 := [26]int{}
shus2 := [26]int{}
// asci码表 https://tool.oschina.net/commons?type=4
//这里 - 'a’的原因是任何一个英文祖母a-z A-z的asci值会大于定义的数组的下标,字母最多有26个,所以需要-‘a’
//注意这里s1[i]获取的是asc码值不是真正的字母
for i := 0; i < len1; i++ {
shus1[s[i] - ‘a’] += 1
}
for j := 0; j < len2; j++ {
shus2[t[j] - ‘a’] += 1
}
return shus1 == shus2
}
}

5 单链表反转(魏龙云 2020-10-25)

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/

红色字体对应的链表代表反转后的链表演变过程,黑色是题目给定的链表结构
在这里插入图片描述

具体代码实现:

LinkList.go
package main
import (
“fmt”
“suanfa/Link”
)
func main(){
// 待添加到链表中的数组
LinkNums := [7]int{1,2,3,4,5,6,7}
// 构造一个空链表 l1不动,最后li是需要待反转的链表
l1 := new (Link.ListNode)
//定义一个临时指针,负责移动并将数组中的元素添加到链表中
temp := l1
for k,v := range LinkNums{
//将元素放入当前temp节点
temp.Val = v
if k == len(LinkNums) - 1{
break
}
//当前temp节点中的next指针指向一个新的空节点
temp.Next = new (Link.ListNode)
//指针向后移动
temp = temp.Next
}
res := Link.ReverseList(l1)
arr := res.GetInt()
fmt.Println(arr)
}

GOPATH/suanfa/Link/common.go
package Link
type ListNode struct {
Val int
Next *ListNode
}
func ReverseList(head *ListNode) *ListNode {
cur := head
var pre *ListNode
for{
if cur != nil{
next := cur.Next
cur.Next = pre
pre = cur
cur = next
}else{
return pre
}
}
}
func (l *ListNode) GetInt() []int {
if l == nil {
return []int{}
}
nums := []int{}
for l != nil {
nums = append(nums, l.Val)
l = l.Next
}
return nums
}

6 旋转图像(伟江 2020-10-25)

https://leetcode-cn.com/problems/rotate-image/
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]

示例 2:
给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]

解题思路
先根据对角线对折,再根据中心对阵对折即可

代码如下:
main.go
package main
import (
“fmt”
“three”
)
func main() {
head := three.CreateList();
// 矩阵顺时针旋转90°
head.PrintList();
var matrix [][]int = [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}}
fmt.Println(matrix)
three.Rotate(matrix)
fmt.Println(matrix)
}

rotate.go
package three
func Rotate(matrix [][]int) {
for i :=0 ; i < len(matrix); i++ {
for j := 0; j < i; j++ {
tmp := matrix[i][j]
matrix[i][j] = matrix[j][i]
matrix[j][i] = tmp
}
}
for i :=0 ; i < len(matrix) / 2; i++ {
for j := 0; j < len(matrix); j++ {
tmp := matrix[j][i]
matrix[j][i] = matrix[j][len(matrix) - 1 - i]
matrix[j][len(matrix) - 1 - i] = tmp
}
}
return
}

7 删除链表的倒数第N个节点(田力2020-11-01)

https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

package three
import “fmt”
// Node 链表中的节点结构体
type Node struct {
val int
next *Node
}
// CreateList 创建一个链表,大小为n
func CreateList(n int) *Node {
// 将1、2、3、4、5添加到链表head中
var head, tmp *Node
head = new(Node)
tmp = head
for i := 1; i <= n; i++ {
tmp.val = i
if i == n {
return head
}
tmp.next = new(Node)
tmp = tmp.next
}
return head
}
// ReverseList 反转head链表
func ReverseList(head *Node) *Node {
var cur, next, pre *Node

for cur = head; nil != cur; cur = next {
	next = cur.next
	cur.next = pre
	pre = cur
}
return pre

}

// PrintList 打印链表
func (l *Node) PrintList() {
if l == nil {
return
}
for ; l != nil; l = l.next {
fmt.Printf("%d “, l.val)
}
fmt.Printf(”\n")
}
// getLen 获取链表的长度
func getLen(l *Node) (length int) {
for cur := l; nil != cur; cur = cur.next {
length++
}
return
}

// 方法一:计算链表长度
// 1、第一次遍历节点得到链表的长度
// 2、第二次遍历到删除节点的前一个结点,
// 并将这个节点的后续节点指向下下个节点
func (head *Node) DelNode(n int) {
length := getLen(head)
// 定义一个哑节点,串联在头节点前面
dummy := &Node{0, head}
cur := dummy
// 删除 size-n
for i := 0; i < length-n; i++ {
cur = cur.next
}
cur.next = cur.next.next
*head = *dummy.next
}

// 时间复杂度:O(n)
// 空间复杂度:O(1)
// 方法二:栈
// DelNode 删除指定下标n对应的节点
func (head *Node) DelNode(n int) {
slice := []*Node{}
dummy := &Node{0, head}
for cur := dummy; nil != cur; cur = cur.next {
slice = append(slice, cur)
}
pre := slice[len(slice)-1-n]
pre.next = pre.next.next
*head = *dummy.next
}

// 时间复杂度:O(n)
// 空间复杂度:O(n)
// 方法三:快慢指针
// DelNode 删除指定下标n对应的节点
func (head *Node) DelNode(n int) {
dummy := &Node{0, head}
first, second := head, dummy
// 快指针先前进n个节点
for i := 0; i < n; i++ {
first = first.next
}
// 同时移动快慢指针
for ; nil != first; first = first.next {
second = second.next
}
second.next = second.next.next
*head = *dummy.next
}
// 时间复杂度:O(n)
// 空间复杂度:O(1)

8 回文数判断(王宇2020-11-01)

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:
输入: 121
输出: true

示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

回文数:1. 定义:回文数是指正序(从左向右)和倒序(从右往左)读都是一样的整数
方法1:数字转换成字符串
举例:整数X:1 2 3 2 1
字符串:“1” “2” “3” “2” “1”
反序字符串:“1” “2” “3” “2” “1”
判断方法:判断字符串和反序字符串是否完全相同
进阶判断方法:判断字符串的前面一半和后面一半是否完全相同就可以了
func isPalindrome(x int) bool {
str:=strconv.Itoa(x)
j:=len(str)-1
for i:=0;i<len(str)/2;i++{
if str[i]!=str[j]{
return false
}
j–
}
return true
}
方法2:将数字本身进行反转
但是这个方法可能会产生数字越界的情况,因此借鉴方法一中进阶解法,就是反转一半数字
负数:- 1 2 3 2 1 负数不可以反转
非负数:
奇数位(关于3对称)
1 2 3 2 1
偶数位(关于 2 之间的虚线对称)
1 2 | 2 1
设置revertedNumber 存储反转后的结果,进行取余的操作,将获取的数字存储到revertedNunber中,之后进行除10的操作,完成舍去最后一位的操作,以此类推进行操作,多次进行上面的过程,我们将得到更多位数的反转数字。
判断终止的条件:当原始数字小于或等于反转后的数字的时候,就意味这我们已经处理了一半位数的数字了。
func isPalindrome(x int) bool {
// 特殊情况1:如上所述,当 x < 0 时,x 不是回文数。
if x < 0 {
return false
}

// 特殊情况2:如果数字的最后一位是 0,为了使该数字为回文,则其第一位数字也应该是:0只有 0 满足这一属性
if x % 10 == 0 && x != 0 {
    return false
}

// 循环建立反转一半的数字
revertedNumber := 0
for x > revertedNumber {
    revertedNumber = revertedNumber * 10 + x % 10
    x /= 10
}
// 奇数和偶数分别判断
return x == revertedNumber || x == revertedNumber / 10

}

时间复杂度:O(logn),这个时间复杂度不是很理解
空间复杂度:O(1)

9 相交链表(魏龙云2020-11-08)

leedcode第160题
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

在这里插入图片描述

main.go
package main
import (
“fmt”
“gosuanfa/link”
)
func main() {
//定义一个数组
LinkNums1 := []int{4,1,9,4,6}
LinkNums2 := []int{5,0,1,9,4,6}
l1 := new(link.ListNode)
l2 := new(link.ListNode)
temp1 := l1
temp2 := l2
for i := 0; i < len(LinkNums1); i++ {
temp1.Val = LinkNums1[i]
if i == len(LinkNums1)-1 {
break
}
temp1.Next = new(link.ListNode)
temp1 = temp1.Next
}
for i := 0; i < 3; i++ {
temp2.Val = LinkNums2[i]
if i == 2 {
break
}
temp2.Next = new(link.ListNode)
temp2 = temp2.Next
}
for i:=2;i<len(LinkNums2);i++{
temp2.Next = l1.Next.Next
}
//listNode类型
l3 := link.GetIntersectionNode(l1,l2)
//l3 := link.GetIntersectionNode1(l1,l2)
//l3 := link.GetIntersectionHash(l1,l2)
resNums := l3.GetInt()
fmt.Println(resNums)
}

linkList.go
package link
type ListNode struct {
Val int
Next *ListNode
}
//length 获取链表的长度
func length(l *ListNode) int{
len := 0
for l != nil{
len++
l = l.Next
}
return len
}
//GetIntersectionNode 获取第一个相交的节点,没有返回nil 第二种方式 长度对齐
func GetIntersectionNode(headA, headB *ListNode) *ListNode {
//获取长度
diff := 0
len1 := length(headA)
len2 := length(headB)
temp1 := headA
temp2 := headB
if len1 > len2{
diff = len1 - len2
}else{
temp1 = headB
temp2 = headA
diff = len2 - len1
}
for i:=0;i<diff;i++{
temp1 = temp1.Next
}
for temp1!= nil{
if temp1 == temp2{
return temp1
}
temp1 = temp1.Next
temp2 = temp2.Next
}
return nil
}
//GetIntersectionNode1 第三种方式 根据总路程
func GetIntersectionNode1(headA, headB *ListNode) *ListNode {
temp1 := headA
temp2 := headB
for temp1 != temp2{
if temp1 == nil{
temp1 = headB
}else{
temp1 = temp1.Next
}
if temp2 == nil{
temp2 = headA
}else{
temp2 = temp2.Next
}
}
return temp1
}
//GetIntersectionHash hashmap方式
func GetIntersectionHash(headA, headB *ListNode) *ListNode {
hashmap := make(map[interface{}]interface{})
for headA != nil{
hashmap[headA] = 1
headA = headA.Next
}
for headB != nil{
if hashmap[headB] == 1{
return headB
}
headB = headB.Next
}
return headB
}
//GetInt 获取链表中的内容
func (l *ListNode) GetInt() []int {
if l == nil {
return []int{}
}
nums := []int{}
for l != nil {
nums = append(nums, l.Val)
l = l.Next
}
return nums
}

9 合并二个有序链表(赵燕伟2020-11-08)

package main
import “fmt”
type ListNode struct {
Val int
Next *ListNode
}
func main() {
l1 := new(ListNode)
l2 := new(ListNode)
temp1 := l1
temp2 := l2
num1 := []int{1, 2, 4}
num2 := []int{1, 3, 4}
for i := 0; i < len(num1); i++ {
temp1.Val = num1[i]
fmt.Println(“wel com”)
if i == len(num1)-1 {
break
}
temp1.Next = new(ListNode)
temp1 = temp1.Next
}
for i := 0; i < len(num2); i++ {
temp2.Val = num2[i]
if i == len(num2)-1 {
break
}
temp2.Next = new(ListNode)
temp2 = temp2.Next
}
l3 := addTwoNumbers(l1, l2)
fmt.Println(l3.getInt())
}
func (l *ListNode) getInt() []int {
if l == nil {
return []int{}
}
nums := []int{}
for l != nil {
nums = append(nums, l.Val)
l = l.Next
}
return nums
}
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
// 如果有一条为nil, 直接返回另一条
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
// 定义头head和移动指针node
var head, node *ListNode
// 选小的那条开始
// 前面判断过l1和l2了,所以这里不可能是空指针
if l1.Val < l2.Val {
head = l1
node = l1
l1 = l1.Next
} else {
head = l2
node = l2
l2 = l2.Next
}
// 循环比较,同时更新
// 始终选择小的值连到node上
for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
// 指向小的那条
node.Next = l1
// 小的往前走
l1 = l1.Next
} else {
node.Next = l2
l2 = l2.Next
}
// 【重要】node往前走
node = node.Next
}
// 循环完了,把剩下的直接放到后面,因为本身就是有序的,所以接在后面就行
if l1 != nil {
node.Next = l1
}
if l2 != nil {
node.Next = l2
}
// 返回最初的那个头
// 这个头不能动,否则找不到了
return head
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值