一、数字串转换为字符串
1-26个数字分别代表26个字符(A-z)输入"12326〞就可以拆分为【1,2,3,2,6】、(12, 3, 2, 6]. [1, 23, 2, 6]【1,23,26】、【12,3,26】等,将每种组合转成成对应字母输出,输出所有可能的结果
返回所有可能的转换结果
// 将数字串转换成字母串
// 将数字串转换成字母串 func numToStr(s string) []string {var result []stringvar path []byte // 用于存储当前路径backtrack(s, 0, &result, path)return result }func backtrack(s string, index int, result *[]string, path []byte) {if index == len(s) { // 如果到达了字符串末尾,将当前路径添加到结果中*result = append(*result, string(path))return}// 一位数情况if index < len(s) {num1 := s[index] - '0' // 转换为数字if num1 >= 1 && num1 <= 9 { // 确保是有效的字母 (1-9)path = append(path, byte('A'+num1-1)) // 将数字转为对应字母backtrack(s, index+1, result, path) // 继续递归path = path[:len(path)-1] // 回溯 }}// 两位数情况if index+1 < len(s) {num2 := (s[index]-'0')*10 + (s[index+1] - '0') // 转换为二位数字if num2 >= 10 && num2 <= 26 { // 确保是有效的字母 (10-26)path = append(path, byte('A'+num2-1)) // 将数字转为对应字母backtrack(s, index+2, result, path) // 继续递归path = path[:len(path)-1] // 回溯 }} }
二、删除搜索二叉树的指定节点
解题思路
当前节点比删除值小,右子树的根变为右子树中删除;
当前节点比删除值大,左子树的根变为左子树中删除;
当前就是要被删的节点,如果它没有左子树或没有右子树,可以直接平移嫁接。
否则需要找到左子树最大值或右子树最小值作为新的根。
链接: https://leetcode.cn/problems/delete-node-in-a-bst/solutions/1531382/-by-himymben-7sey/
/*** Definition for a binary tree node.* type TreeNode struct {* Val int* Left *TreeNode* Right *TreeNode* }*/ func deleteNode(root *TreeNode, key int) *TreeNode {if root != nil {if root.Val < key {root.Right = deleteNode(root.Right, key)} else if root.Val > key {root.Left = deleteNode(root.Left, key)} else {if root.Left == nil || root.Right == nil {if root.Left != nil {root = root.Left} else {root = root.Right}} else {node := root.Leftfor node.Right != nil {node = node.Right}node.Left = deleteNode(root.Left, node.Val)node.Right = root.Rightroot = node}}}return root }
三、字符串数字相乘
题目:给定两个以字符串形式表示的非负整数 num1
和 num2
,返回 num1
和 num2
的乘积,它们的乘积也表示为字符串形式。
num1
和num2
的长度小于110。num1
和num2
只包含数字0-9
。num1
和num2
均不以零开头,除非是数字 0 本身。- 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理
基于竖式乘法,先逐位乘算,再进位相加:
func multiply(num1 string, num2 string) string {// 有0参与直接返回0if num1 == "0" || num2 == "0" {return "0"}// 某个为1直接返回另一个if num1 == "1" {return num2}if num2 == "1" {return num1}// 定义map用于暂存每一位的临时结果tmp := map[int]rune{}// 按照逐位相乘,错位相加的思想,遍历计算i := 0for _, a := range num1 {j := 0for _, b := range num2 {tmp[i+j] += (a - 48) * (b - 48)j++}i++}var (c runeres string)// 逐位相加后连接字符串for i := len(tmp) - 1; i >= 0; i-- {tmp[i] += cc = tmp[i] / 10res = string([]rune{tmp[i]%10 + 48}) + res}// 将最后一个进位连接上if c != 0 {res = string([]rune{c + 48}) + res}return res }
链接: https://segmentfault.com/a/1190000021756333?utm_source=tag-newest
四、打家劫舍ii
func rob(nums []int) int {n := len(nums)//细分情况dp0, dp1 := [2]int{0, 0}, [2]int{0, nums[0]}if n < 2{ // 仅有一个元素的特殊情况,容易遗漏return dp1[1]}// 照搬dp 方程for i := 1; i < n; i++{dp0[0], dp0[1] = max(dp0[0], dp0[1]), dp0[0] + nums[i]dp1[0], dp1[1] = max(dp1[0], dp1[1]), dp1[0] + nums[i]}return max(dp0[0], dp0[1], dp1[0]) } func max(nums ...int)int{m := nums[0]for _, c := range nums{if m < c{m = c}}return m }
链接:https://leetcode.cn/problems/house-robber-ii/solutions/1097624/geng-wei-jian-ji-de-golang-ban-ben-by-hz-6fdl/
五、无序数组第k大
#include <iostream> #include <cstring>using namespace std;int func(int *arr, int l, int r, int k) {if (k-1 < l || k-1 > r){return -1;}int p = l;int key = arr[r];for (int i = l; i < r; ++i){if (arr[i] > key){int tmp = arr[p];arr[p] = arr[i];arr[i] = tmp;p++;}}if (p == k-1){return key;}else if (p > k-1){return func(arr, l, p-1, k);}else{arr[r] = arr[p];return func(arr, p+1, r, k);} }int main() {int arr[] = {12,43,56,7,90,7,0,8,58,32,21};int len = sizeof(arr) / sizeof(int);int *tmp = new int[len];for (int i = -1; i <= len+1; ++i){memcpy(tmp, arr, sizeof(arr));cout << func(tmp, 0, len-1, i) << ' ';}delete[] tmp;return 0; }
链接: https://www.cnblogs.com/zuofaqi/p/10209648.html
七、无序数组前k大 快排实现
这个算法的基本思想是基于快速排序,它通过选取一个“基准”元素,将数组分成两个部分:小于基准的和大于基准的。然后根据需要的个数决定继续在哪一部分进行查找。
package mainimport ("fmt""math/rand" )// partition将数组分为两部分,小于等于pivot的放到左侧,大于pivot的放到右侧 func partition(arr []int, left, right, pivotIndex int) int {pivotValue := arr[pivotIndex]// Swap pivot with the rightmost elementarr[pivotIndex], arr[right] = arr[right], arr[pivotIndex]storeIndex := leftfor i := left; i < right; i++ {if arr[i] > pivotValue { // 找前k大的,所以是大于arr[storeIndex], arr[i] = arr[i], arr[storeIndex]storeIndex++}}// Move pivot to its final placearr[right], arr[storeIndex] = arr[storeIndex], arr[right]return storeIndex }// quickSelect返回数组中前k大的元素 func quickSelect(arr []int, left, right, k int) []int {if left <= right {// Randomly select a pivot indexpivotIndex := left + rand.Intn(right-left+1)pivotIndex = partition(arr, left, right, pivotIndex)// Check the position of the pivotif pivotIndex == k {return arr[:k]} else if pivotIndex < k {return quickSelect(arr, pivotIndex+1, right, k)} else {return quickSelect(arr, left, pivotIndex-1, k)}}return nil }// FindTopK 返回无序数组中的前k大元素 func FindTopK(arr []int, k int) []int {if k <= 0 || k > len(arr) {return nil}return quickSelect(arr, 0, len(arr)-1, k) }func main() {arr := []int{3, 2, 1, 5, 6, 4}k := 2topK := FindTopK(arr, k)fmt.Println(topK) // 输出前k大的元素 }
八、两个有序数组合并
由题可知,我们需要将第二个数组的元素合并到第一个数组之后返回
两个数组都是有序的,因此对于每个想要插入数组的元素,我们只要找到首个大于这个元素的数,将其插入到这个数的前方即可
复杂度分析
时间复杂度:O(m+n)执行的循环次数为数组二的个数n,也就是插入数组一的元素个数,再加上指针搜索插入位置的移动长度,最坏情况等于数组一的长度m
空间复杂度:O(1),常数次空间
func merge(nums1 []int, m int, nums2 []int, n int) {k:=0for i:=0;i<n;i++{for nums1[k]<=nums2[i]{if(k==m) {break}k++}copy(nums1[k+1:m+1],nums1[k:m])m++nums1[k]=nums2[i]} }
链接: https://segmentfault.com/a/1190000041355583
九、中文数字转换为整数
下面是一个用 Go 语言实现的函数,它将中文数字(不超过一亿)转换为整数。代码中考虑了中文数字的各种形式,包括“万”、“千”、“百”等单位,并处理了零的情况。
### 代码说明:
1. **映射表**:
- `chineseNumbers` 用于存储中文数字字符到对应整数的映射。
- `units` 用于存储中文单位字符(如“十”、“百”、“千”、“万”)到其对应数值的映射。
2. **主逻辑**:
- 循环遍历输入字符串中的每个字符。
- 如果字符是中文数字,则将其添加到当前累计值 `current`。
- 如果字符是单位,更新 `current` 的值。如果遇到“万”,则将 `current` 加入到 `result` 中,并重置 `current` 为 0。
- 最后将任何剩余的 `current` 添加到结果 `result` 中。
3. **错误处理**:
- 对于无效字符,返回错误。
### 示例输出:
对于输入 `"六千四百八十五万七千四百零八"`,输出将是:
```
The integer value is: 64857408
```
func chineseToInt(s string) (int, error) {chineseNumbers := map[rune]int{'零': 0,'一': 1,'二': 2,'三': 3,'四': 4,'五': 5,'六': 6,'七': 7,'八': 8,'九': 9,}units := map[rune]int{'十': 10,'百': 100,'千': 1000,'万': 10000,}// 清理输入,移除多余的空格并统一为半角s = strings.TrimSpace(s)result := 0current := 0for _, ch := range s {if num, exists := chineseNumbers[ch]; exists {current += num} else if unit, exists := units[ch]; exists {if unit == 10 && current == 0 {current = 1 // "十"前面没有数字时,视为 "一十" }current *= unitif unit == 10000 {result += currentcurrent = 0}} else {return 0, fmt.Errorf("invalid character: %c", ch)}}result += currentreturn result, nil }func main() {input := "六千四百八十五万七千四百零八"result, err := chineseToInt(input)if err != nil {fmt.Println("Error:", err)} else {fmt.Printf("The integer value is: %d\n", result)} }
十、最大连续子数组和
### 代码说明:
- **maxSubArray 函数**:
- 输入一个整数数组 `nums`。
- 使用两个变量 `maxSum` 和 `currentSum` 来跟踪最大和当前的连续子数组和。
- 使用 `start`, `end`, 和 `tempStart` 来记录当前的子数组的起始和结束索引。
- 当 `currentSum` 小于零时,重置 `currentSum` 并更新 `tempStart` 为当前元素的索引。
- 如果找到一个更大的 `currentSum`,则更新 `maxSum` 并记录新的子数组的起始和结束位置。
### 运行结果:
对于输入 `arr := []int{-2, 1, -3, 4, -1, 2, 1, -5, 4}`,输出将是:
```
Maximum subarray: [4 -1 2 1]
Maximum sum: 6
```
该代码能够处理所有情况,包括整个数组为负数。这种情况下,它将返回数组中最大的单个元素。
func maxSubArray(nums []int) ([]int, int) {if len(nums) == 0 {return nil, 0}maxSum := nums[0]currentSum := nums[0]start := 0end := 0tempStart := 0for i := 1; i < len(nums); i++ {if currentSum < 0 {currentSum = nums[i]tempStart = i // reset the start index} else {currentSum += nums[i]}if currentSum > maxSum {maxSum = currentSumstart = tempStartend = i // update end index }}return nums[start : end+1], maxSum }func main() {arr := []int{-2, 1, -3, 4, -1, 2, 1, -5, 4}subArray, sum := maxSubArray(arr)fmt.Printf("Maximum subarray: %v\n", subArray)fmt.Printf("Maximum sum: %d\n", sum) }
十一、零钱凑数
map优化
// coinChange 计算最少需要多少硬币来凑成指定金额 func coinChange(coins []int, amount int) int {// 定义备忘录count := make([]int, amount+1)for i := range count {count[i] = math.MaxInt32 // 初始化为最大值 }count[0] = 0 // 零金额需要零个硬币 res := help(coins, count, amount)return res }// help 函数进行递归DFS遍历所有可能性 func help(coins []int, count []int, amount int) int {// 如果备忘录中已经保存结果if count[amount] < math.MaxInt32-1 {// 直接返回return count[amount]}minRes := math.MaxInt32for _, coin := range coins {if amount-coin >= 0 {// 递归调用res := help(coins, count, amount-coin)if res >= 0 && res < minRes {minRes = res + 1}}}// 更新备忘录if minRes == math.MaxInt32 {count[amount] = -1} else {count[amount] = minRes}// 返回结果return count[amount] }func main() {coins := []int{1, 2, 5}amount := 11result := coinChange(coins, amount)fmt.Println(result) // 输出最少需要的硬币数 }
复杂度分析
时间复杂度: 时间复杂度为O(mn),其中m
为coins
中元素的个数,n
为要兑换的总金额。
空间复杂度: 空间复杂度为O(n),n
为要兑换的总金额。
#
链接: https://www.ldtiger.com/pages/289b40/#c-%E4%BB%A3%E7%A0%81