给定一个数n如23121;给定一组数字a如[2 4 9],求由a中元素组成的小于n的最大数

a: 1-9的不同数字

n:int32

分析

从n的高位到低位遍历 假设当前位是bit, 找寻arr满足条件的数分类讨论:

  1. 找到arr[i] == bit, 当前位置更新为bit,继续遍历低位
  2. 找到最大的arr[i] < bit, 那么当前位置更新位arr[i], 后面所有位置全部更新为 max(arr)
  3. min(arr) > bit, 当前位找不到比n更小,舍弃所有高位,低位全部选最大

经过上述的遍历筛选之后,能得到两个答案:

  1. 满足条件的最大。直接返回即可。
  2. 找到ans==n。继续分析ans==n,从低位遍历ans的每一位,从arr中找更小的一个值替换a. 找到值,替换,返回替换后的ansb. 所有值遍历完,找不到更小,所有位置都是min(ans) 那么返回0,表示找不到更小值

实现

Golang

func solve(n int, arr []int) int {
	// 将n从高位到低位用数组存储,方便按位置检索
	// 123 => []int{1,2,3}
	nArr := []int{}
	for n > 0 {
		// 加到数组前面
		nArr = append([]int{n % 10}, nArr...)
		n /= 10
	}
	// 将arr进行排序,方便找寻min,max 寻值可以用2分,更快,不过因为arr长度最大只有9[1-9], 所以也可以直接遍历
	sort.Ints(arr)
	// 按梳理条件分类讨论
	ans := 0
	// 从高位开始,定位n的位置
	pos := 0
	for pos < len(nArr) {
		bit := nArr[pos]
		pos++
		// 找到第一个>bit的索引idx, 那么arr[idx-1] <= bit
		idx := 0
		for idx < len(arr) && arr[idx] <= bit {
			idx++
		}
		if idx == 0 {
			// 当前找不到比bit更小的值,往前看有没有位置可以选更小元素
			// 1. 找到,那么该位置选择更小,后续位置全部最大
			// 2. 没有找到,前置全部是最小值,则舍弃最高位,后续位置全部选最大
			// pos当前在下一位,回到上一位,-2
			pos -= 2
			for pos >= 0 {
				cur := ans % 10
				ans /= 10
				if arr[0] == cur {
					pos--
					continue
				}
				// 存在更小值,找到更小值,替换
				idx := 0
				for arr[idx] < cur {
					idx++
				}
				ans = ans*10 + arr[idx-1]
				pos++
				break
			}
			// 如果没有找到,则去除最高位,此时ans=0
			if pos <= 0 {
				pos = 1
			}
			// 低位全部选择最大
			for pos < len(nArr) {
				ans = ans*10 + arr[len(arr)-1]
				pos++
			}
			return ans
		}
		// arr[idx-1] 是小于等于bit的最大值
		if arr[idx-1] < bit {
			ans = ans*10 + arr[idx-1]
			// 低位全部选择最大
			for pos < len(nArr) {
				ans = ans*10 + arr[len(arr)-1]
				pos++
			}
			return ans
		}
		// arr[idx-1] == bit
		ans = ans*10 + bit
		// 继续遍历低位
	}
	// 循环内没找到答案,此时ret=n 逆序遍历,找到更小的位置,替换
	pos = len(nArr) - 1
	for pos >= 0 {
		bit := nArr[pos]
		pos--
		idx := 0
		// 找到arr[idx]=bit, idx-1为要的元素
		for idx < len(arr) && arr[idx] < bit {
			idx++
		}
		// 找到了
		if idx > 0 {
			ans = ans*10 + bit
			for pos >= 0 {
				bit := nArr[pos]
				ans = ans*10 + bit
				pos--
			}
			// 因为是逆序遍历得到的答案,所以将ret逆序
			return reverse(ans)
		}
		// 没找到,继续遍历
		ans = ans*10 + bit
	}
	// 没找到
	return 0
}

func reverse(v int) int {
	ans := 0
	for v > 0 {
		ans = ans*10 + v%10
		v /= 10
	}
	return ans
}

验证:

示例1:
23121
[4,2,9]
22999

示例2:
19238479
[1,4,2,3,7]
17777777

示例3:
192482
1,5,3,2
155555

示例4:
333112342
4,5,6,7
77777777

示例5:
4441242
4,5,6
666666

示例6:
23121
2,3,4
22444

全部评论
case5感觉应该是666666吧
1 回复 分享
发布于 02-27 16:14 广东
// 循环内没找到答案,此时ret=n 逆序遍历,找到更小的位置,替换 循环内没找到答案 是否直接return ans就行 代表每一位都完全相同或者一位都没计入
点赞 回复 分享
发布于 03-04 21:01 上海

相关推荐

评论
1
3
分享

创作者周榜

更多
牛客网
牛客企业服务