《剑指offer》---Go语言实现

数组中重复的数字

题目描述:
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

解法一:

简单解法:
因为数字范围一定在0-n-1之间,表示可以使用哈希表来解决这个问题。
建立一个数组切片number,长度为n,下标则表示0-n-1,初始化数组切片为0,只要顺序遍历原数组,将原数组中的数字v拿出查看对应切片下标中的数字,如果为0则加1,如果为1则表示这个数字重复。
时间复杂度:O(n)
空间复杂度:O(n)

代码实现:

func findRepeatNumber(nums []int) int {
    number :=make([]int,len(nums))
    for _,v:=range nums{
        if number[v]==0{
            number[v]++
        }else{
            return v
        }
    }
    return 0
}

同样的思路,也可以用map实现。

func findRepeatNumber(nums []int) int {
    m:=make(map[int]int,len(nums))
    for _,v:=range nums{
        if _,ok:=m[v];ok{
            return v
        }else{
            m[v]=1
        }
    }
    return -1
}

解法二:
改变数组的数字位置,因为数字大小在0-n-1,所以如果不重复,则每一位可以对应相应的数字下标。
我们可以扫描原数组,发现下标和数字相等则可以,如果不相等,就让这个数字和相对应下标的数字替换,直到找到对应下标和数字相等。如果在这个过程中,发现下标和数字不想等,但是数字和对应下标位置的数字相等则说明重复。

func findRepeatNumber(nums []int) int {
    // 改变数组位置
    for i,v:=range nums{
        for v!=i{
            if v==nums[v]{
                return v 
            }
            v,nums[v]=nums[v],v
        }
    }
    return -1
}

时间复杂度:O(n)
空间复杂度:O(1)

二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

题解:
这道题总体比较容易理解。向下和向右都是数字递增的,就可以从第一行且最右列开始查询,因为如果比当前数字小就可以直接向左移动(因为向下都是比它大的),如果比当前数字大就直接向下查询(因为向左都是比它小的),最后数字在其中肯定能查询到,返回true即可。

func findNumberIn2DArray(matrix [][]int, target int) bool {
    if len(matrix)==0||len(matrix[0])==0{
        return false
    }
    columnindex:=len(matrix[0])-1
    rowindex:=0
    for columnindex>=0&&rowindex<=len(matrix)-1{
        if target<matrix[rowindex][columnindex]{
            columnindex--
        }else if target>matrix[rowindex][columnindex]{
            rowindex++
        }else{
            return true
        }
    }
    return false
}

替换空格

题目描述:

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

我写的还是很像C++代码,自己看了一些别人的Go代码,感觉很简洁

func replaceSpace(s string) string {
    if len(s)==0{
        return ""
    }
    countSpace:=0
    for i:=0;i<len(s);i++{
        if s[i]==' '{
            countSpace++
        }
    }
    Newlength:=len(s)+countSpace*2
    replaceArray:=make([]byte,Newlength)
    j:=len(s)-1
    for i:=Newlength-1;i>=0;i--{
        if s[j]==' '{
            replaceArray[i]='0'
            i--
            replaceArray[i]='2'
            i--
            replaceArray[i]='%'
        }else{
             replaceArray[i]=s[j]
        }
        j--
    }
    return string(replaceArray)
}

Go解法:

func replaceSpace(s string) string {
    var res strings.Builder
    for i:=range s{
        if s[i]==' '{
            res.WriteString("%20")
        }else{
            res.WriteByte(s[i])
        }
    }
    return res.String()
}
func replaceSpace(s string) string {
    var res []rune
    for _,v:=range s{
        if v==32{
            res=append(res,37,50,48)
        }else{
            res=append(res,v)
        }
    }
    return string(res)
}

从尾到头打印链表

题目描述:

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

解法一:

遍历链表,然后将数组反转

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    var result []int
    if head==nil{
        return result 
    }
    var temp *ListNode=head 
    for temp!=nil{
        result=append(result,temp.Val)
        temp=temp.Next
    }
    for i,j:=0,len(result)-1;i<=j;{
        result[i],result[j]=result[j],result[i]
        i++
        j--
    }
    return result
}

解法二:

遍历链表,用栈存储。但是go语言中并没有栈操作,我们可以用list来当作栈进行操作。

func reversePrint(head *ListNode) []int {
    if head==nil{
        return nil 
    }
    var result []int 
    var stack list.List 
    for head!=nil{
        stack.PushBack(head.Val)
        head=head.Next
    }
    for stack.Len()>0{
        value:=stack.Back()
        stack.Remove(value)
        result=append(result,value.Value.(int))
    }
    return result
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值