面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • 算法

  • 数据结构

  • 设计模式

  • CMU硕士经典100题

  • 剑指offer

    • 3-10
    • 11-20
    • 21-30
    • 31-40
    • 41-50
      • 41.数据流中的中位数
      • 42.连续子数组的最大和
        • 解法一: 动态规划
      • 43.1~n整数中1出现的次数
      • 44.数字序列中某一位的数字
        • 解法一: 迭代
      • 45.把数组排成最小的数
        • 解法一: 自定义排序
      • 46.把数字翻译成字符串
        • 解法一: 动态规划
        • 解法二: 数字求余
      • 47.礼物的最大价值
        • 解法一: 动态规划
      • 48.最长不包含重复字符串的子字符串
        • 解法一: 动态规划+哈希表
        • 解法二: 动态规划+线性遍历
        • 解法三: 双指针+哈希表
      • 49.丑树
        • 解法一: 动态规划
      • 50.第一个只出现一次的字符
        • 解法一: 使用数组来存储频次
    • 51-60
    • 61-70
  • 重点手撕代码

  • 程序员面试

  • CodeTop企业题库

  • 笔试题目

  • 算法和数据结构
  • 剑指offer
小游
2021-03-29

41-50

# 41.数据流中的中位数

剑指 Offer 41. 数据流中的中位数 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407114305529

这题先暂时跳过,后续再来研究一下

# 42.连续子数组的最大和

剑指 Offer 42. 连续子数组的最大和 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407150421561

# 解法一: 动态规划

可能是我题目做多了吧~,居然做出来了哈哈。

func maxSubArray(nums []int) int {
   // 如果长度为0,那么我们直接返回0
   if len(nums) == 0 {
      return 0
   }
   // 设当前值为最大
   max:=nums[0]
   // 然后我们开始遍历整个数组
   for i := 1; i < len(nums); i++ {
      // 当前的最大值有两种情况,要么当前是最大,要么是前一个加上当前这个最大
      nums[i] = Max(nums[i-1]+nums[i],nums[i])
      // 然后我们找出最大值就可以了
      if max < nums[i] {
         max = nums[i]
      }
   }
   return max
}

func Max(a int,b int) int {
   if a > b {
      return a
   } else {
      return b
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 43.1~n整数中1出现的次数

剑指 Offer 43. 1~n 整数中 1 出现的次数 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407152829826

看到大佬的题解又觉得自己行了,但是看了一下,算了我是垃圾,先跳过吧。。。。

# 44.数字序列中某一位的数字

剑指 Offer 44. 数字序列中某一位的数字 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407160236103

这题目的难点在于如何找出这个规律,我现在这种能力还非常欠缺。。。。

# 解法一: 迭代

唉,还是直接看大佬的题解吧,下面这个是我们得到的数学规律

Picture1.png

image-20210407194504953

确定好大致范围后我们还需要进行细分

Picture2.png

Picture3.png

Picture4.png

func findNthDigit(n int) int {
   // digit表示数位
   // start表示起始数字
   // count表示数位的数量
   digit:=1
   start:= 1
   count:= 9
   // 当n小于数位数量的时候,我们就退出循环
   for n > count {
      // 这里是根据我们的数学规律进行计算得到的
      n-=count
      digit+=1
      start*=10
      count=digit*start*9
   }
   // num表示所求数位在第几个数字中
   num:=start+(n-1)/digit
   // 然后这里确定我们的数位
   return int(strconv.Itoa(num)[(n-1)%digit] - '0')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 45.把数组排成最小的数

剑指 Offer 45. 把数组排成最小的数 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407194702208

。。。。。这种题真的完全没有思路。。。这题刷的我好难受啊

# 解法一: 自定义排序

这题本质上也是排序,只是由之前的排数字变成了排序字符串,我们把这些东西排好序后就可以得出结果了

image-20210407201443745

func minNumber(nums []int) string {
   // 处理边界情况,如果数组为空或长度为0
   if nums == nil || len(nums) == 0 {
      return "" // 返回空的字符串
   }
   // 否则定义一个长度为n的字符串数组
   strs := make([]string, len(nums))
   // 遍历整数数组,把整数转成字符串,并存储到字符串数组
   for i := range nums {
      strs[i] = strconv.Itoa(nums[i])
   }
   // 接下来对字符串进行排序,注意这里要自定义对比规则
   sort.Slice(strs, func(i, j int)bool{
      // 先把两种字符串的拼接结果写出来
      s12 := strs[i]+strs[j]
      s21 := strs[j]+strs[i]
      // 如果字符串s12小于s21,那么我们希望s1排在s2前面。
      return s12<s21
   })
   // 把数组中的字符串依次拼接起来
   var buffer bytes.Buffer
   for i := range strs{
      buffer.WriteString(strs[i])
   }
   return buffer.String()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 46.把数字翻译成字符串

剑指 Offer 46. 把数字翻译成字符串 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210407211005610

又是一道不会的题。。。这种题还是自己练的太少了唉

# 解法一: 动态规划

动态规划的题目难就难在如何找出状态方程,本题的状态方程如下

image-20210408083919543

func translateNum(num int) int {
   // 为了方便计算我们先把数字转换为字符串
   s := strconv.Itoa(num)
   // 然后使用a,b来暂存,a表示i-2 b表示i-1
   a := 1
   b := 1
   // 然后我们开始计算
   for i := 2; i <= len(s); i++ {
      // 每次截取两个字符
      tmp := s[i-2 : i]
      var c int
      // 然后比较一下大小
      if tmp >= "10" && tmp <= "25" {
         c = a + b
      } else {
         c = a
      }
      b = a
      a = c
   }
   return a
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 解法二: 数字求余

上面的动态规划虽然省略了dp占用的控件,但是还需要字符串s

利用求余运算 num % 10 和求整运算 num // 10 ,可获取数字 num 的各位数字

func translateNum(num int) int {
   a:=1;b:=1;x,y:=num%10,num%10
   for num!=0 {
       // num/10 来获取各位情况
      num/=10
      // x相当于10位,然后y相当于个位
       x=num%10
       // 计算tmp,tmp就是要比较的值
      tmp:=10*x+y
      var c int
      if tmp >= 10 && tmp <= 25 {
         c = a+b
      } else {
         c = a
      }
      b = a
      a = c
      y = x
   }
   return a
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 47.礼物的最大价值

剑指 Offer 47. 礼物的最大价值 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210408085114507

居然做出来了,太激动了,主要是以前做过差不多的哈哈哈

# 解法一: 动态规划

func maxValue(grid [][]int) int {
   if len(grid) == 0 {
      return 0
   }
   // 获取grid的长度和宽度
   m,n:=len(grid),len(grid[0])
   // 初始化dp数组
   dp:=make([][]int,m)
   // dp数组分配空间
   for i:=0;i<m;i++{
      dp[i] = make([]int,n)
   }
   // 因为我们只能向下或者向右,所以我们直接可以算出顶部和左边的值
   dp[0][0] = grid[0][0]
   // 顶部和左边都是固定的
   for i:=1;i<m;i++{
      dp[i][0] = grid[i][0] + dp[i-1][0]
   }
   for i:=1;i<n;i++{
      dp[0][i] = grid[0][i]+ dp[0][i-1]
   }
   // 然后我们计算其他部分的
   for i:=1;i<m;i++ {
      for j:=1;j<n;j++ {
         // 因为根据我们的状态方程,当前最大值要么是上面的+当前的,要么是左边+当前的,我们选一个最大的即可
         dp[i][j] = max(dp[i-1][j],dp[i][j-1])+grid[i][j]
      }
   }
   return dp[m-1][n-1]
}

func max(a int,b int) int {
   if a > b {
      return a
   } else {
      return b
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

不过我这解法还是有点不足的地方就是需要额外申请空间的。所以我们这里可以直接在原数组的基础上进行计算,这样就省去了dp数组

func maxValue(grid [][]int) int {
   if len(grid) == 0 {
      return 0
   }
   // 获取grid的长度和宽度
   m,n:=len(grid),len(grid[0])
   // 顶部和左边都是固定的
   for i:=1;i<m;i++{
      grid[i][0] += grid[i-1][0]
   }
   for i:=1;i<n;i++{
      grid[0][i] += grid[0][i-1]
   }
   // 然后我们计算其他部分的
   for i:=1;i<m;i++ {
      for j:=1;j<n;j++ {
         // 因为根据我们的状态方程,当前最大值要么是上面的+当前的,要么是左边+当前的,我们选一个最大的即可
         grid[i][j] += max(grid[i-1][j],grid[i][j-1])
      }
   }
   return grid[m-1][n-1]
}

func max(a int,b int) int {
   if a > b {
      return a
   } else {
      return b
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 48.最长不包含重复字符串的子字符串

剑指 Offer 48. 最长不含重复字符的子字符串 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210408102422162

# 解法一: 动态规划+哈希表

因为我们要统计连续的不重复字符串,所以我们必须使用map来暂存数据,然后判断是否重复,然后我们使用tmp来暂存

test

func lengthOfLongestSubstring(s string) int {
   // 使用动态规划
   dic:=make(map[byte]int)
   // res存储最终结果,然后tmp表示dp[i]
   res:=0;tmp:=0
   // 遍历整个s
   for j := 0; j < len(s); j++ {
      // 默认i的值为-1,表示dic里面没有
      var i = -1
      // 如果当前字符串在map里面存在,我们就返回当前字符串的位置
      if _, ok := dic[s[j]]; ok {
         i=dic[s[j]]
      }
      // 更新一下map
      dic[s[j]] = j
      // 判断是当前的大还是j-i的大
      if tmp < j-i {
         tmp++
      } else {
         tmp=j-i
      }
      // 获取最大值
      res = max(res,tmp)
   }
   return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 解法二: 动态规划+线性遍历

func lengthOfLongestSubstring(s string) int {
   // res表示最终结果,tmp表示当前位置下最长的子字符串
   res:=0;tmp:=0
   // 开始进行遍历
   for i := 0; i < len(s); i++ {
      j:=i-1
      // 找出第一个和当前位置重复的元素
      for j >= 0 && s[j] != s[i] {
         j--
      }

      if tmp < i-j {
         tmp++
      } else {
         tmp = i-j
      }
      // 找出一个最大值
      res=max(res,tmp)
   }
   return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 解法三: 双指针+哈希表

我们使用两个指针来表示,如果不重复那么就完全加,如果发现重复的,我们就更新一下位置

func lengthOfLongestSubstring(s string) int{
   // 使用dic来暂存数据
   dic:=make(map[byte]int)
   // res设置为0,j默认为-1
   res:=0;j:=-1
   // 遍历整个字符串
   for i := 0; i < len(s); i++ {
      // 当我们的字符串已经存在时
      if _,ok:=dic[s[i]];ok {
         // 这里我们更新一下j的位置(取最大是为了每次获取最后的,避免重复)
         j=max(j,dic[s[i]])
      }
      // 然后我们更新一下位置信息
      dic[s[i]] = i
      // 更新一下最大值即可
      res=max(res,i-j)
   }
   return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 49.丑树

剑指 Offer 49. 丑数 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210408200537789

唉,对这种数学规律的题目我真的已经无感了。。。我怎么这么菜啊。。。

# 解法一: 动态规划

func nthUglyNumber(n int) int {
   // 因为丑树是包含质因子2,3,5的数,所以我们就分别哟经abc来进行表示
   a:=0;b:=0;c:=0
   // 初始化dp数组
   dp:=make([]int,n)
   dp[0] = 1
   for i:=1;i<n;i++ {
      // 我们分别求一下每个质因子和较小的数相乘得到的结果
      an:=dp[a]*2;bn:=dp[b]*3;cn:=dp[c]*5
      // 当前的丑数值就应该上面三个的最小值
      dp[i] = min(an,min(bn,cn))
      // 判断一下是哪个最小,然后我们更新一下下标
      // 因为我们要确保丑数要每个质因子都要乘一下,所以我们采用3个下标的方式
      if dp[i] == an { a++ }
      if dp[i] == bn { b++ }
      if dp[i] == cn { c++ }
   }
   return dp[n-1]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 50.第一个只出现一次的字符

剑指 Offer 50. 第一个只出现一次的字符 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

image-20210408203124657

害,太难了,本来以为可以直接使用map来解决,但是最后发现go遍历map居然是随机的。。。

# 解法一: 使用数组来存储频次

我傻了,傻乎乎的想怎么找到第一个值,一直在研究数组,但是最后才发现,我直接再遍历一般字符串不就行了。。。

func firstUniqChar(s string) byte {
   cnt:=[26]int{}
   // 遍历整个数组
   for i := 0;i<len(s);i++{
      cnt[s[i]-'a']++
   }
   // 继续遍历
   for i := 0; i < len(s); i++ {
      // 找出第一个为1的值,找到后我们立马退出
      if cnt[s[i]] == 1 {
         return s[i]
      }
   }
   return ' '
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
编辑 (opens new window)
上次更新: 2021/04/08, 21:41:12
31-40
51-60

← 31-40 51-60→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式