Algorithm一天一道算法


一天一道算法题

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

//解法一
func twoSum1(nums []int, target int) []int {
	//遍历所有的加法组合,直到找到符合相加得到目标数的两个数,并且两数不是同一个数
   l:=len(nums)
   for i:=0;i<l-1;i++{
      for j:=1;j<l;j++{
         if target==nums[i]+nums[j]&&i!=j{
            return []int{i,j}
         }
      }
   }
   return nil
}
//这种方法比较笨,且较慢,时间复杂度O(n^2)

//解法二
func twoSum2(nums []int, target int) []int {
   //创建一个map存储遍历后的数组对,键值对个数为数组长度
   num2index := make(map[int]int, len(nums))
   //遍历数组
   for i, num := range nums {
      //核心是用目标值减去循环遍历出来的值,判断是否是数组内的值
      pair := target - num
      //
      if j, ok := num2index[pair]; ok && i != j {
         // 注意返回值顺序,向后遍历 nums,所以 i 在 j 后
         return []int{j, i}
      }
      //循环一边就存入map
      //第一遍map[2]=0,没有相同
      //第二遍map[7]=1,没有相同且存在pair := target - num

      num2index[num] = i
   }
   return nil
}
//这种方法虽牺牲空间但速度快,时间复杂度O(log2n)

2.翻转字符串

给定一串字符串,将字符串进行翻转

示例1:输入”abc”,输出”cba”;

示例2:输入”1313adfasf”,输出”fsada3131”;

//解法
func Reverse(s string) string {
    //[]rune符文是int32的别名,在所有方面都与int32等效。按照惯例,它用于区分字符值和整数值。
   a := []rune(s)
    //从两端开始进行转变位置
   for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
       //go语言内部会构造一个虚拟变量
      a[i], a[j] = a[j], a[i]
   }
   return string(a)
}

3.回文判断

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

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

例如,121 是回文,而 123 不是。

//我的解法
func isPalindrome(x int) bool {
    //负数不是回文
   if x<0 {
      return false
   }
    //提示:转为字符串方便
   a:=strconv.Itoa(x)
   s:=[]rune(a)
   l:=len(s)
    //由翻转想到的灵感,不是最好
   for i,j:=0,l-1;i<j;i,j=i+1,j-1{
      if s[i]!=s[j]{
         return false
      }
   }
   return true
}

4.最大容器问题

给定一个长度为 n 的整数数组height。有n条垂线,第 i 条线的两个端点是(i, 0)和(i, height[i])。
找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为49。
示例 2:

输入:height = [1,1]
输出:1

// 两条线段之间的面积受限与最短的线段,线段间距越长,面积越大
// 使用 2 个指针指向首部和尾部,将短指针向长指针方向移动,看能不能找到更长的线,使面积更大
// 依据:向长线方向每次移动 1 格,虽然宽度-1,但是(高度变高)*(宽度-1) >= 高度*宽度
// 双指针法
func maxArea(height []int) int {
	maxarea:=0
	//分别取左右两个指针
	for i,j:=0,len(height)-1;i<j {
		//面积等于短指针高度*两个指针距离
		maxarea=max(maxarea,min(height[i],height[j])*(j-i))
		//如果右指针更高,则左指针向右一格
		if height[i]<height[j] {
			i++
			//反之,右指针向左一格
		}else {
			j--
		}
	}
	return maxarea
}
//两数最小
func min(a,b int) int{
	if a>b {
		return b
	}else{
		return a
	}
}
//两数最大
func max(a,b int) int {
	if a>b {
		return a
	}else{
		return b
	}
}

5.最长前缀问题

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串””。

示例 1:

输入:strs = [“flower”,”flow”,”flight”]
输出:”fl”
示例 2:

输入:strs = [“dog”,”racecar”,”car”]
输出:””
解释:输入不存在公共前缀。

package main

import (
    "fmt"
    "strings"
)

func main() {
	//test1
    fmt.Println(longestCommonPrefix([]string{"flower", "fly", "flight"})) // fl
	//test2
    fmt.Println(longestCommonPrefix([]string{"dog", "racecar", "car"}))   // ""
}

// 维护一个前缀库,不断往后遍历,判断前缀逐步剪短前缀库的大小
func longestCommonPrefix(strs []string) string {
    if len(strs) <= 0 {
        return ""
    }
    s1 := strs[0]
    prefixes := make([]string, len(s1))
	//将第一个字符串遍历为一个字符串前缀库
	//test1:[]prefixes{"f","fl","flo","flow","flowe","flower"}
    for i := range s1 {
        prefixes[i] = s1[:i+1]
    }
    //遍历输入的字符串数组
    for _, s := range strs {
        for i, pre := range prefixes {
			//HasPrefix判断字符串s是否以pre前缀开头。
            if !strings.HasPrefix(s, pre) {
                prefixes = prefixes[:i]
                break
            }
        }
    }
    if len(prefixes) > 0 {
		//返回最后一个字符串即最长前缀
        return prefixes[len(prefixes)-1]
    }
    return ""
}

文章作者: hypo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hypo !
评论
  目录