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

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

摘要 :本文将对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)。

参考

相关推荐
bbppooi25 分钟前
排序学习整理(1)
c语言·数据结构·学习·算法·排序算法
且听风吟72037 分钟前
JS综合解决方案5——模块化和构建工具
javascript·面试
海绵波波1071 小时前
集群聊天服务器面试问题
运维·服务器·面试
是糖不是唐1 小时前
代码随想录算法训练营第五十五天|Day55 图论
c语言·数据结构·算法·图论
seabirdssss1 小时前
力扣_876. 链表的中间结点
java·数据结构·算法·leetcode·链表
JhonKI2 小时前
【算法】BFS解决最短路径问题
算法·php·宽度优先
加德霍克2 小时前
数据结构之算法
数据结构·学习·算法·排序算法
GZ_TOGOGO3 小时前
【干货分享】Boosting算法简单案例
算法·机器学习·boosting
就是有点傻3 小时前
C#中面试的常见问题004
面试·职场和发展·c#·wpf
码上有前3 小时前
【51-60期】深入解析Java面试问题:从高并发到性能调优的最佳实践
java·开发语言·面试