算法编程题-寻找最近的回文数

算法编程题-寻找最近的回文数

摘要 :本文将对LeetCode 原题 564 寻找最近的回文数进行讲解,并且给出golang语言的实现,该实现通过了所有测试用例且执行用时超过100%的提交,最后给出相关的复杂度分析。
关键词:算法、LeetCode、Golang、分情况讨论

原题描述

LeetCode 564 寻找最近的回文数: 给定一个表示数字的字符串n,求最近的回文数,如果有多个回文数与n的差的绝对值相等,则优先取较小的数。

思路简述

这道题相对比较复杂,没有任何的技巧,只是将所有情况考虑进去,需要分情况讨论所有情况,然后从这些情况下的回文数进行比较,选出最符合条件的。怎么去分情况讨论呢?

要构造一个比较接近的回文数,一种思路是将数都前半部分直接对应到后半部分,这样生成的既是一个回文数,相对来说比较地接近原来的回文数,这种能解决大部分问题,但是还存在一些特殊情况。一种是要将前半部分加一再对应到后半部分,还需要减一再对应到后半部分。此外,加一减一可能导致数位的变化,所以还要将位数减一的最大的回文数和位数加一最小的回文数也加入到待考虑的集合中。更加详细的过程请参考代码实现:

代码实现

go 复制代码
func nearestPalindromic(n string) string {
	nums := []byte(n)
	m := len(nums)
	flag := false
	backUpNums := make([]string, 0)
	for i := m - 1; i >= m/2; i-- {
		if nums[i] != nums[m-1-i] {
			flag = true
			nums[i] = nums[m-1-i]
		}
	}
	if flag { // flag标识是否有修改
		backUpNums = append(backUpNums, string(nums))
	}
	// 考虑将前半部分加一后构造
	c := byte(1)
	for i := m / 2 + m % 2 - 1; i >= 0; i-- {
		nums[i] += c
		if nums[i] > '9' {
			nums[i] -= 10
			c = 1
		} else {
			break
		}
	}
	for i := m - 1; i >= m / 2; i-- {
		nums[i] = nums[m - 1 - i]
	}
	backUpNums = append(backUpNums, string(nums))

	// 考虑将前半部分减一后构造
	nums = []byte(n)
	c = byte(1)
	for i := m / 2 + m % 2 - 1; i >= 0; i-- {
		nums[i] = nums[i] + 10 - c
		if nums[i] > '9' {
			nums[i] -= 10
			break
		} else {
			c = 1
		}
	}
	for i := m - 1; i >= m / 2; i-- {
		nums[i] = nums[m - 1 - i]
	}
	backUpNums = append(backUpNums, string(nums))
	// 再加上两个位数加一减一的回文数
	backUpNums = append(backUpNums, buildMaxPalind(m - 1), buildMinPalind(m + 1))
	res := ""
	for _, num := range backUpNums {
		if res == "" || less(strSub(n, num), strSub(n, res)) || ((strSub(n, num) == strSub(n, res) && less(num, res))) { {
			res = num
		}
	}
	return res
}

func buildMaxPalind(n int) string {
	if n == 0 {
		return "0"
	}
	res := make([]byte, n)
	for i := 0; i < n; i++ {
		res[i] = '9'
	}
	return string(res)
}

func buildMinPalind(n int) string {
	if n == 0 {
		return "0"
	}
	res := make([]byte, n)
	for i := 0; i < n; i++ {
		res[i] = '0'
	}
	res[0] = '1'
	res[n - 1] = '1'
	return string(res)
}

// strSub 字符串加减
func strSub(str1, str2 string) string {
	if str1 == str2 {
		return "0"
	}
	if less(str1, str2) {
		return strSub(str2, str1)
	}
	m := len(str1)
	n := len(str2)
	res := make([]byte, m)
	k := m - 1
	i := m - 1
	j := n - 1
	c := byte(0)
	for i >= 0 || j >= 0 {
		t := str1[i] + 10 - c
		if j >= 0 {
			t -= str2[j]
		}
		if t > 9 {
			t -= 10
			c = 0
		} else {
			c = 1
		}
		if t < '0' {
			t += '0'
		}
		res[k] = t
		k--
		i--
		j--
	}
    for res[k + 1] == '0' && k < m - 1 {
        k++
    }
	return string(res[k+1:])
}

// less 返回str1 是否小于str2
func less(str1, str2 string) bool {
	m := len(str1)
	n := len(str2)
	if m < n {
		return true
	}
	if m > n {
		return false
	}
	for i := 0; i < m; i++ {
		if str1[i] > str2[i] {
			return false
		} else if str1[i] < str2[i] {
			return true
		}
	}
	return false
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),n为字符串数字的长度
  • 空间复杂度: O ( n ) O(n) O(n),也可以实现 O ( 1 ) O(1) O(1)。

参考

相关推荐
8Qi828 分钟前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
秋935 分钟前
Go语言(Golang)开发工程师全景解析:岗位职责·语言优势与使用场景·各城市薪资·发展前景·高考志愿填报(2026版)
开发语言·golang·高考
mONESY1 小时前
JavaScript 栈、队列、数组与链表核心知识点总结
javascript·面试
贺国亚1 小时前
电商AI辅助交易场景
面试
youngerwang2 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
chase_my_dream2 小时前
C++ + SLAM 高频面试问题整理
开发语言·c++·面试
想要成为糕糕手2 小时前
前端必修课:JavaScript 数组与数据结构底层逻辑全解析
javascript·数据结构·面试
KaMeidebaby2 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠3 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
swipe3 小时前
做多轮对话 Agent,为什么我建议把短期记忆放到 Redis
后端·面试·llm