给定固定长度的字符串,求解按字符字典序排列,该字符串是第几小?
2017-09-20 18:16
543 查看
题目:
现有‘abcdefghijkl’12个字符,将其所有的排列按字典序进行排序,给出任意一组排列,说出这租排列在所有排列中是第几小的?
解题思路:
假如,给出的第一位是b(给出的这个字符串简称str),那么所有以a开头的字符串都会排在str前面。以a开头的字符串的数量就是后面11位字符所有的排列组合,也就是11的阶乘。
如果第一位是c,那么所有以a或者b开头的所有字符串就会排在str的前面,也就是 2*11!,依次类推,可以知道第一位是任意字符时排在str前面的字符串的数量。接着看第二位,第二位的思路和第一位一样,同样可以知道第二位是任意字符时排在str前面的字符串的数量,以此类推,后面的字符都算完之后,把全部结果相加。
但是,这个时候还有一个问题,在这道题中12个字符是固定的,所以假如第一位不是a,是b,那么a在后面的字符中一定会出现,同时b也不会再出现,所以在进行上面的计算时,不能直接以字典序来进行计算,在计算每一位时要根据尚未出现过的字符的顺序,来排列未出现的字符的顺序。
关于尚未出现过的字符的顺序,有两种思路,一种是将出现过的字符放到字符串最前面,另一种是使用StringBuffer求解,将出现过的字符直接删除,不在考虑,只考虑剩下字符的字典序。
实现代码:
package com.zxt.algorithm;
import java.util.Scanner;
/**
*
* @author zxt
*
*/
public class SequenceSort {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
String[] str = new String
;
for (int i = 0; i < n; i++) {
str[i] = sc.nextLine();
System.out.println(getSortNum(str[i]));
}
}
// System.out.println(getSortNum("abcdefghijkl")); // 1
// System.out.println(getSortNum("hgebkflacdji")); // 302715242
// System.out.println(getSortNum("gfkedhjblcia")); // 260726926
//
// System.out.println(getSortNum2("abcdefghijkl")); // 1
// System.out.println(getSortNum2("hgebkflacdji")); // 302715242
// System.out.println(getSortNum2("gfkedhjblcia")); // 260726926
sc.close();
}
/**
* 样例输出
*
* System.out.println(getSortNum("abcdefghijlk")); // 1
* System.out.println(getSortNum("hgebkflacdji")); // 302715242
* System.out.println(getSortNum("gfkedhjblcia")); // 260726926
*/
// 程序分析:例如hgebkflacdji,第一位取出来是h,本来h应该在第七位(sort中得到该值),所以第七位前的所有字母在第一位的顺序都应该比这个字符串顺序靠前
// 接下来分析第二位的字符,此时相当于h的顺序已经固定,不用在考虑,所以将它放到第一位
public static int getSortNum(String value) {
// 记录已经出现过的字符和未出现的字符顺序
String sort = "abcdefghijkl";
int res = 1;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
// 查看该字符在所有字符中的当前顺序
int head = sort.lastIndexOf(c);
// 计算排在前面的字符串数量
res += ((head - i) * factorial(11 - i));
// 修改字符顺序,将当前出现的字符,交换到字符最前面,因为我们不关心已经出现过得字符的顺序,我们只要知道出现过哪些字符以及未出现的字符的字典序
sort = change(sort, head);
}
return res;
}
// 按照该思路,其实我们可以使用StrinfBufer,先按字典序保存下12个字符,然后将当前出现的字符直接删除就好了。
// 然后重新计算,再计算下一个字符的本来的位置,从而确定有几个字符排在它前面。
public static int getSortNum2(String value) {
// 记录已经出现过的字符和未出现的字符顺序
StringBuffer sort = new StringBuffer("abcdefghijkl");
int res = 1;
for (int i = 0; i < value.length(); i++) {
String c = value.charAt(i) + "";
// 查看该字符在所有字符中的当前顺序
int head = sort.lastIndexOf(c);
// 计算排在前面的字符串数量 (sort.length()-1)表示全排列,即第一位是b,那么所有以a开头的字符串都会排在它前面的意思
res += ((head) * factorial(sort.length() - 1));
// 将出现过的字符删除
sort.deleteCharAt(head);
}
return res;
}
/**
* 求阶乘
*/
public static int factorial(int n) {
int result = 1;
if (n == 0) {
result = 0;
} else {
for (int i = 1; i <= n; i++) {
result *= i;
}
}
return result;
}
/**
* 将字符串第index位换到最前面
*/
public static String change(String str, int index) {
StringBuffer temp = new StringBuffer(str.charAt(index) + "");
for (int i = 0; i < str.length(); i++) {
if (i != index) {
temp.append(str.charAt(i));
}
}
return temp.toString();
}
}
现有‘abcdefghijkl’12个字符,将其所有的排列按字典序进行排序,给出任意一组排列,说出这租排列在所有排列中是第几小的?
解题思路:
假如,给出的第一位是b(给出的这个字符串简称str),那么所有以a开头的字符串都会排在str前面。以a开头的字符串的数量就是后面11位字符所有的排列组合,也就是11的阶乘。
如果第一位是c,那么所有以a或者b开头的所有字符串就会排在str的前面,也就是 2*11!,依次类推,可以知道第一位是任意字符时排在str前面的字符串的数量。接着看第二位,第二位的思路和第一位一样,同样可以知道第二位是任意字符时排在str前面的字符串的数量,以此类推,后面的字符都算完之后,把全部结果相加。
但是,这个时候还有一个问题,在这道题中12个字符是固定的,所以假如第一位不是a,是b,那么a在后面的字符中一定会出现,同时b也不会再出现,所以在进行上面的计算时,不能直接以字典序来进行计算,在计算每一位时要根据尚未出现过的字符的顺序,来排列未出现的字符的顺序。
关于尚未出现过的字符的顺序,有两种思路,一种是将出现过的字符放到字符串最前面,另一种是使用StringBuffer求解,将出现过的字符直接删除,不在考虑,只考虑剩下字符的字典序。
实现代码:
package com.zxt.algorithm;
import java.util.Scanner;
/**
*
* @author zxt
*
*/
public class SequenceSort {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
String[] str = new String
;
for (int i = 0; i < n; i++) {
str[i] = sc.nextLine();
System.out.println(getSortNum(str[i]));
}
}
// System.out.println(getSortNum("abcdefghijkl")); // 1
// System.out.println(getSortNum("hgebkflacdji")); // 302715242
// System.out.println(getSortNum("gfkedhjblcia")); // 260726926
//
// System.out.println(getSortNum2("abcdefghijkl")); // 1
// System.out.println(getSortNum2("hgebkflacdji")); // 302715242
// System.out.println(getSortNum2("gfkedhjblcia")); // 260726926
sc.close();
}
/**
* 样例输出
*
* System.out.println(getSortNum("abcdefghijlk")); // 1
* System.out.println(getSortNum("hgebkflacdji")); // 302715242
* System.out.println(getSortNum("gfkedhjblcia")); // 260726926
*/
// 程序分析:例如hgebkflacdji,第一位取出来是h,本来h应该在第七位(sort中得到该值),所以第七位前的所有字母在第一位的顺序都应该比这个字符串顺序靠前
// 接下来分析第二位的字符,此时相当于h的顺序已经固定,不用在考虑,所以将它放到第一位
public static int getSortNum(String value) {
// 记录已经出现过的字符和未出现的字符顺序
String sort = "abcdefghijkl";
int res = 1;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
// 查看该字符在所有字符中的当前顺序
int head = sort.lastIndexOf(c);
// 计算排在前面的字符串数量
res += ((head - i) * factorial(11 - i));
// 修改字符顺序,将当前出现的字符,交换到字符最前面,因为我们不关心已经出现过得字符的顺序,我们只要知道出现过哪些字符以及未出现的字符的字典序
sort = change(sort, head);
}
return res;
}
// 按照该思路,其实我们可以使用StrinfBufer,先按字典序保存下12个字符,然后将当前出现的字符直接删除就好了。
// 然后重新计算,再计算下一个字符的本来的位置,从而确定有几个字符排在它前面。
public static int getSortNum2(String value) {
// 记录已经出现过的字符和未出现的字符顺序
StringBuffer sort = new StringBuffer("abcdefghijkl");
int res = 1;
for (int i = 0; i < value.length(); i++) {
String c = value.charAt(i) + "";
// 查看该字符在所有字符中的当前顺序
int head = sort.lastIndexOf(c);
// 计算排在前面的字符串数量 (sort.length()-1)表示全排列,即第一位是b,那么所有以a开头的字符串都会排在它前面的意思
res += ((head) * factorial(sort.length() - 1));
// 将出现过的字符删除
sort.deleteCharAt(head);
}
return res;
}
/**
* 求阶乘
*/
public static int factorial(int n) {
int result = 1;
if (n == 0) {
result = 0;
} else {
for (int i = 1; i <= n; i++) {
result *= i;
}
}
return result;
}
/**
* 将字符串第index位换到最前面
*/
public static String change(String str, int index) {
StringBuffer temp = new StringBuffer(str.charAt(index) + "");
for (int i = 0; i < str.length(); i++) {
if (i != index) {
temp.append(str.charAt(i));
}
}
return temp.toString();
}
}
相关文章推荐
- 截取固定长度字符串显示在页面,多余部分显示为省略号(区分汉字和字符)
- 截取固定长度字符串显示在页面,多余部分显示为省略号(区分汉字和字符)
- 筛选固定长度的字符串并在其后添加字符
- 给定一个字符串s由大小写字母和空白字符组成,返回字符串中最后一个字的长度。 如果最后一个字不存在,则返回0。
- 字典序问题。在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写字母组成。该字母表产生的升序字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1
- SQL截取非固定长度(有关键字符)的字符串
- Java实现给定任一字符串,长度为任意,要求找出其出现次数最多的字符及其出现次数。
- 递归问题之一:给定一字符串,输出字符串中所有字符子串的各种组合形式,长度为一个字符到字符串的长度,忽略排序
- 给定一个字符串A,同时给定它的长度n及参数字符数组arg,请返回替换后的字符串
- 截取固定长度字符串显示在页面,多余部分显示为省略号(区分汉字和字符)
- python给定n个字符串,请对n个字符串按照字典序排列
- Java生成固定长度的字符串,长度不足自动填充指定字符
- 字典序问题。在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写字母组成。该字母表产生的升序字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1
- 对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符。 给定一个字符串(不一定全为字母)A及它的长度n。请返回第一个重复出现的字符。保证字符串中有重复字符,字符串的长度小于等于500。
- 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length
- 给定一个字符串,找到最长的子串的长度没有重复字符
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
- 请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。 给定一个string
- C# "125" 转换位“00000125” 左边使用固定字符补充为固定长度的字符串
- 给定n个字符串,请对n个字符串按照字典序排列