给定一个正整数(以数字数组的形式)。我们可以交换给定数字中的一对数字。我们需要返回可以获得的最小整数。注意,它应该是一个有效的整数,即不应该包含前导0。
例如:-
这个问题是否有O(n)
算法。我想出了几种方法:-
O(n^2)
。 < li >生成数字和索引的< code>std::pair的< code >数组/向量,并按升序排序(根据数字值;首先为匹配的数字值保留较低的索引)。遍历排序后的数组。将MSB与第一个数字交换。如果最小数位的索引为MSB,则将MSB与下一个最小数位交换1位。如果下一个min数字对应的索引是MSB,但只有1位,那么用这个下一个min交换MSB,但只有2位。数字等等。这应该是< code>O(nlog(n))。
有人可以建议一个更好的算法。
更新1:经过一点思考,我提出的第二个算法将非常好地工作(可能除了少数可以单独处理的拐角情况外)。此外,我可以使用计数排序(根据数字值)对对(数字、索引)进行排序,这在O(n)
时间内是一种稳定的排序。我的论点有缺陷吗?
更新2:我的第二个算法可以工作(尽管需要更多检查角点大小写和0),在O(n)
时间内,使用计数排序
。但@GaborSch给出的解决方案要简单得多,所以我不会为我的算法给出合适的代码。
我会从右端开始遍历数组。将右侧的数字存储为最小数字和最大数字,然后开始向左移动,如果你碰到一个新的较小的数字,将其称为潜在最小数。如果你继续向左移动,找到一个较小的数字,将较小的数字设为潜在数。如果你找到一个较大的数字,将潜在数设为最小int,并将较大的整数存储为最大数字。每次你碰到比最小数更大的数字,将其设为新的最大数字。如果你碰到结尾,交换最大数字和最小数字。在python中(这是有效的,并且是O(n))
def swap_max(digits):
i = len(digits) - 1
while i > 0:
if digits[i] == 0:
i-= 1
else:
break
max_i = i
min_i = i
pot_i = i
z_i = -1
nz_i = i
i = len(digits) - 1
while i >= 0:
if digits[i] > digits[pot_i]:
max_i = i
min_i = pot_i
if digits[i] < digits[min_i] and digits[i] != 0:
pot_i = i
if digits[i] == 0 and z_i == -1:
z_i = i
if digits[i] != 0 and i > 0:
nz_i = i
i -= 1
if z_i != -1 and max_i != 0 and max_i < z_i:
min_i = z_i
i = nz_i
max_i = i
elif max_i == min_i and z_i != -1:
i = nz_i
if i < z_i:
min_i = z_i
max_i = i
v = digits[min_i]
digits[min_i] = digits[max_i]
digits[max_i] = v
return digits
#TESTING THE FUNCTION
tests = [93561,596,10234,120,10091,98761111,1001,1010,1103,120,93218910471211292416]
results = [13569,569,10234,102,10019,18761119,1001,1001,1013,102,13218910471211292496]
tests = map(list,map(str,tests))
results = map(list,map(str,results))
for i in range(len(tests)):
res ="".join(map(str,swap_max(map(int,tests[i]))))
print res,"".join(results[i])
if res=="".join(results[i]):
print "PASSED\n"
else:
print "FAILED\n"
这最终适用于所有示例。它还具有O(1)内存使用的优势。
首先计算每个数字,将其存储在一个数组中(计数[10]
)。
从左侧开始,检查数字(以下是循环说明):
检查< code >计数中是否有比它小的数字。挑个最小的。例外:第一个数字不允许< code>0。
计数
中的数字,并转到下一个数字对于每个数字,你做O(1)工作。所以整个算法是O(n)。
对于交换,您需要使用最低有效数字(进一步向右)。您可以在初始查找时存储这些位置,也可以在交换之前从末尾开始搜索第一个匹配的数字。
作为准备工作,我们遍历数字,并标记数组中数字的最后位置[10](称为最后
)(包括0
秒)。那就是 O(n)。
接下来,我们开始从左到右遍历数字。对于每个位置,我们试图找到最后一个位置大于当前位置的最小数字(位置约束)。此外,该数字必须小于当前数字。
如果我们处于第一个位置,我们将从1
开始在最后一个
>上开始循环(否则从0
如果我们找到这样一个数字(关于位置约束),我们就交换(并中断循环)。如果我们不这样做,我们就前进到下一个数字。成本最多为O(n*9),即O(n)。
总成本为O(n)O(n)*O(9)=O(n)。
该算法如何在示例上工作:
93561 -> it can swap in the first cycle
596 -> skipping the first cycle,
then finds '6' because of the position constraint
(comparing position '1' with last[5] = 0, last[6] = 2)
10234 -> does not find anything because of the position constraint
93218910471211292416 -> finds the last occurrence of '1' to replace '9'
98761111 -> it can swap in the first cycle
(last[1] = 7, so it will change the last occurrence)
555555555555555555596 -> iterates until the '9', then you skip last[5]
but finds last[6] as a good swap
120 -> at pos 0 (1) cannot find a non-zero element less than 1, so skip
at pos 1 (2) can find 0 on position 2, so we swap
同样,这里我们对数字进行一次迭代(用于预解析数据),然后一次迭代寻找MSB。在第二次迭代中,我们迭代< code>last
,它的大小不变(最多为9)。
您可以通过添加跟踪最小值来进一步优化算法,当值得在last
上开始循环时,但这已经是一种优化了。prevoius版本包含它,如果您感兴趣,请查看历史记录:)
给定一个无序整数列表,以这种方式打印两个总计为的整数(int 1小于或等于int 2,它们之间用空格隔开)。假设整数列表中总是有的解。int1和int2必须是正整数。 如果有多个解决方案,请打印差异最小的整数对。 例子: 这是我的代码,但是根据我们的编译器(这是我们班的一个练习),我对隐藏的测试用例有错误的输出。 更新:代码工作!
我试着写一个代码,它接受一个介于1和1_000_000之间的整数,并返回一个比相同数字的整数大的最小整数,如果它不存在,则打印0。 举个例子 输入:156 输出165 输入330 输出0 输入27711 输出71127 我的问题是,下面的代码没有为其他输入返回正确的输出。 例如,在输入4231中,输出应该是4312。 我很难找到为每个输入返回正确输出的最佳算法。 TNX提前 }
给定一个2d数组,我需要返回一个具有路径的矩阵,该路径递归地求和到给定的数字。 路径矩阵应为零,但总计为给定数字的路径除外,该路径将标记为1。 路径只能在 我尝试过所有的可能性,首先检查我是否已经去过下一个街区。 问题是在一些迭代之后,它会停止,并且不会返回并再次将块清除为0。 给定 在通话中 我以为算法会回来 我得到 相反 调用paintPath(mat1400,path,0,0);我想 或 问
我知道这是一个背包问题,其中权重和值相等,但我认为我在编码逻辑上犯了一个错误,因为即使对于数组中元素的数量(N)为50并且所需的最大总和(M)4500。 为了澄清这个问题,我们得到了一个由N个正整数和一个正整数M组成的数组。数组元素只能使用一次。我们必须找到这个数组的子集(不一定是连续的),使得总和最接近M,但不超过它。 这是我使用动态编程的尝试: 那么在我的代码中是否有任何可能的优化可以帮助我降
正整数的二进制权重是其二进制表示中1的个数。例如,十进制数1的二进制权重为1,十进制数7(二进制为111)的二进制权重为3。 给定一个正整数N,找出与N具有相同二进制权重的大于N的最小整数。 我的解决方案运行良好,但它的复杂性似乎是O(NlogN)。这可以通过其他方法在O(N)或O(logn)中实现吗?
我试图解决下面提供的Codness中的一个问题, 编写一个函数: 给定一个由N个整数组成的数组A,返回A中不出现的最小正整数(大于0)。 例如,给定A=[1,3,6,4,1,2],函数应该返回5。 假定: N是范围[1...100,000]内的整数;数组A的每个元素都是范围[−1,000,000..1,000,000]内的整数。 预期最坏情况时间复杂度为O(N);预计最坏情况下的空间复杂度为O(N