算法每日一练
重新排列空格
给你一个字符串 text ,该字符串由若干被空格包围的单词组成。每个单词由一个或者多个小写英文字母组成,并且两个单词之间至少存在一个空格。题目测试用例保证 text 至少包含一个单词 。
请你重新排列空格,使每对相邻单词之间的空格数目都 相等 ,并尽可能 最大化 该数目。如果不能重新平均分配所有空格,请 将多余的空格放置在字符串末尾 ,这也意味着返回的字符串应当与原 text 字符串的长度相等。
返回 重新排列空格后的字符串 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rearrange-spaces-between-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解答:
python3
class Solution:
def reorderSpaces(self, text: str) -> str:
c = text.count(" ")
print(text)
li = text.strip().split()
print(li)
if len(li) == 1:
return li[0] + " " * c
s, s1 = divmod(c, len(li) - 1)
return (" " * s).join(li) + " " * s1
if __name__ == '__main__':
s = Solution()
req = s.reorderSpaces(" this is a sentence ")
print(req)
有点东西: split()默认什么不加,以分割字符串中的any whitespace。divmod函数返回商和余
golang:
package main
import (
"strings"
)
func reorderSpaces(text string) string {
req := strings.Fields(text)
sSpace := strings.Count(text, " ")
k := sSpace/(len(req)-1)
j := sSpace%(len(req)-1)
spaceK := ""
spaceJ := ""
for i:=0;i<k;i++{
spaceK += " "
}
if j!=0{
for i:=0;i<j;i++{
spaceK += " "
}
}
l := strings.Join(req, spaceK) + spaceJ
return l
}
func main(){
reorderSpaces(" this is a sentence ")
}
有点东西:go中的取商和余不知道math中是否有方法,重复的字符串拼接用的for循环,go中的join是切片,字符串
重新排列数组
给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,...,xn,y1,y2,...,yn] 的格式排列。
请你将数组按 [x1,y1,x2,y2,...,xn,yn] 格式重新排列,返回重排后的数组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shuffle-the-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
python:
class Solution:
def shuffle(self, nums: list, n: int) -> list:
req = []
for i in range(n):
req.append(nums[i])
req.append(nums[i+n])
return req
golang:
func shuffle(nums []int, n int) []int {
var req []int
for i:=0; i<n;i++{
req = append(req, nums[i])
req = append(req, nums[i+n])
}
return req
}
没东西
最少硬币组合
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
python:
class Solution:
def coinChange(self, coins: list, amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for x in range(coin, amount + 1):
dp[x] = min(dp[x], dp[x - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
golang
package main
import "math"
import "fmt"
func coinChange(coins []int, amount int) int {
inf := math.Inf(1)
reslutSlice := []float64{}
for i := 0; i < amount+1; i++ {
reslutSlice = append(reslutSlice, inf)
}
reslutSlice[0]=0
for _, coin := range coins {
for j := coin; j < amount+1; j++ {
reslutSlice[j] = math.Min(reslutSlice[j], reslutSlice[j-coin]+1)
}
}
for _,h := range reslutSlice{
fmt.Println(h)
}
if reslutSlice[amount] != inf {
return int(reslutSlice[amount])
} else {
return -1
}
}
func main() {
coins := []int{1, 2, 3}
req:=coinChange(coins, 6)
fmt.Println(req)
}
动态规划-上台阶
给定 n 节台阶,每次可以走一步或走两步,求一共有多少种方式可以走完这些台阶。
from functools import lru_cache
@lru_cache() # cache记录,自动记录迭代中已经运算过的结果
def c_st(n):
if n <= 2:
return n
return c_st(n-1) + c_st(n-2)
req = c_st(8)
print(req)
动态规划-house robber
假如你是一个劫匪,并且决定抢劫一条街上的房子,每个房子内的钱财数量各不相同。如果
你抢了两栋相邻的房子,则会触发警报机关。求在不触发机关的情况下最多可以抢劫多少钱。
Input: [2,7,9,3,1]
Output: 12
import time
from functools import lru_cache
# @lru_cache()
def test(in_list):
if len(in_list) == 0:return 0
if len(in_list) == 1:return in_list[0]
if len(in_list) == 2:return max(in_list[0], in_list[1])
cur = max(in_list[-1]+test(in_list[0:-2]), test(in_list[0:-1]))
return cur
in_list =[2,7,9,3,1,23,4,12,43,5,23,75,523,45,77,2,34,98,3,50,34]
@lru_cache()
def test1(n):
if n > len(in_list): return
if n == 0:return in_list[0]
if n == 1:return max(in_list[0], in_list[1])
p1 = in_list[0]
p2 = max(in_list[0], in_list[1])
cur = 0
for i in range(2, n+1):
cur = max(p1+in_list[i], p2)
p1 = p2
p2 = cur
return cur
有点东西:第二种压缩了空间复杂度为O(n),并且利用lru cache进行了计算结果的cache。并且总体来说for循环的运算速度好于递归。递归时间:0.015955209732055664 for循环时间0.0
动态规划-计算等差数组
给定一个数组,求这个数组中连续且等差的子数组一共有多少个。
Input: nums = [1,2,3,4]
Output: 3
def is_spl(n_list):
if len(n_list) < 3:return False
for i in range(len(n_list)-2):
if n_list[i+1] - n_list[i] != n_list[i+2] - n_list[i+1]:
return False
return True
def test(tmp):
if len(tmp) < 3:return 0
a = -3
sum = 0
while True:
if is_spl(tmp[a:]):
sum += 1
if abs(a) == len(tmp):
break
a -= 1
cur = test(tmp[0:-1]) + sum
return cur
req = test([1,2,3,4,5,6])
print("req", req)
动态规划-二维数组路径最短
给定一个 m × n 大小的非负整数矩阵,求从左上角开始到右下角结束的、经过的数字的和最
小的路径。每次只能向右或者向下移动。
Input:
[[1,3,1],
[1,5,1],
[4,2,1]]
Output: 7
a = [
[1,3,1],
[1,5,1],
[4,2,1]
]
m = len(a[0])-1
n = len(a)-1
from math import inf
from functools import cache
@cache
def test(x, y):
if x < 0 or y < 0:
return float('inf')
print(x, y)
try:
a[x][y]
except IndexError:
return float('inf')
min_e = min(test(x, y-1), test(x-1, y))
print("min_e", min_e)
if min_e == inf:
return a[x][y]
else:
return min_e + a[x][y]
req = test(2, 0)
print(req)