对于学习编程的小伙伴们来说,Top Coder 一定是一个不错的学习的平台。下面的链接的部分的英文的引用:
https://www.topcoder.com/problem-of-the-week-greedy-algorithms-math-and-permutations/
This week, we’ll analyze a problem from SRM 497. This problem featured
as the Division I Level One problem and the Division II Level Two
problem. The summary of the problem is as follows – Given a string S
of size N consisting of “I”s and “D”s, where an “I” denotes a pair in
ascending order, and a “D” denotes a pair in descending order,
construct the lexicographically smallest permutation of size N+1
consisting of the first N+1 natural numbers that match the string’s
characters, if possible. For example, “DDI” would generate “3 2 1 4”
as when we check every adjacent pair, the order is
“decreasing-decreasing-increasing” Similarly, “IID” would generate “2
3 4 1” or “1 2 4 3” — so our answer here would be “1 2 4 3” as we need
to generate the lexicographically smallest result. Let’s break the
problem into two parts –
- What do we if we encounter “I” – Since we’re dealing with a permutation of numbers, we can’t repeat numbers and so the smartest
move we can make is assign the new number to the value of the smallest
number larger than all current numbers. Thus, if we’re looking at the
Xth index, the smallest number larger than all previous numbers in our
current permutation will be X. This statement can be proved by
induction.- What do when if encounter “D” – A “D” implies the next number in the permutation is smaller than the current number at the end of the
permutation, implying that we need to insert a smaller number. Upon
inserting this smaller number, we’ll have to iterate over the
permutation again and make sure we increment every element greater
than or equal to this new number to “make space” for it and preserve
the uniqueness of each element. So the question now comes down to
“which number to insert?” Let us re-insert the current last number and
then iterate over all previous elements and increment only those
elements greater than or equal to the new last element. The reason
this mathematically works is because for all previous elements greater
than or equal to the new last element –If X < Y then X+1 < Y+1 Similarly, if X > Y, then X+1 > Y+1
The translation is below:
这周,我们将分析一个从SRM 497 上的问题。问题的特点是第一部分是I级问题,第二级是II级问题。
问题的概述如下— 给定一个字符串,大小是N,包含’I’ 和‘D’;‘I’的意思是一对数字以升序排列,‘D’的意思一对数字以降序排列,构建一个按照字母表最小的排列,大小为N+1 ,包含N+1 个自然数,这些自然数符合字符串的特点,如果可能的话。例如:
“DDI”会生成’3 2 1 4’ ,当我们检查每一个相邻的数字对,顺序是”降序–降序–升序“。
类似的,
“IID” 会生成“2 3 4 1” 或者是"1 2 4 3"----因此这里我们的答案是“1 2 4 3”,因为我们需要生成字典顺序最小的值。
让我们把这个问题分解成两个部分。
1,如果我们遇到了‘I’,我们该做什么。 既然我们处理的是数字的排列的问题,我们不能重复数字,我们可以做的最小的一步是让新分配的数字的值比当前所有的数字要大一些。这样,如果我们看看在第X个索引,比我们当前的排列中所有先前的数字都要大的最小的数字将是X 。这个语句可以用归纳法来证明。
2,如果我们遇到了’D‘,我们该做什么。 一个‘D’意味在排列的下一个数比在排列的末尾的当前的数要小,意思是我们需要插入一个更小的数。插入一个较小的数之后,我们需要再一次遍历这个排列,确保我们增加每一个数字元素比这个新增加的元素大或者相等来“创造空间”并且保持每一个元素的唯一性。于是这个问题现在变成了“插入哪一个数?”让我们再插入当前最后的一个数,然后遍历所有之前的元素并且只增加那些比最新的最后的一个元素大或者相等元素。数学上行得通的原因是因为对于所有之前的元素比新的最后一个元素大或者相等符合下面的规则:
if X<Y then X+1 <Y+1 Similarly ,if X >Y ,then X+1 >Y+1
这样,我们就被允许来对所有的元素增加1,这些元素比最新的最后一个元素大或者相等。
import java.util.*;
import java.util.regex.*;
import java.text.*;
import java.math.*;
public class PermutationSignature {
public int[] reconstruct(String s) {
int n = s.length() + 1;
int[] ans = new int[n];
ans[0] = 1;
for (int i = 1; i < n; ++i) {
if (s.charAt(i - 1) == 'I') {
ans[i] = i + 1;
} else {
ans[i] = ans[i - 1];
}
for (int j = 0; j < i; ++j) {
if (ans[j] >= ans[i]) {
ans[j]++;
}
}
}
return ans; }
}
在TopCoder 上不仅可以可以通过解决问题提高自己的算法的能力,还会遇到志同道合的朋友,下面的链接是TopCoder官网。大家有兴趣可以躲在上面学习学习,共同进步。
TopCoder:
https://www.topcoder.com