#题目:
有n个正整数(每个数小于10亿),将它们表示成字符串形式。对每一个字符串s,
可以翻转为新字符串s’,如“1234”可以翻转成“4321”。现在,
将这n个字符串以任意顺序连成一个字符环,每个字符串可以选择是否翻转。在字符环中,
从任意一个位置开始,遍历整个环,得到一个长整数。请问,如何才能得到最大的长整数
举例:9,98,23,56,56,998 1
要反转的 :23->32 56->65
得到数组: 9 98 32 65 65 998 1
最后得到的最大的长整数是 9 998 98 65 65 32 1
#method 正确的解法:字符串排序
这题的考点是字符串排序,而非数字排序。
在排序过程中使用 Comparator 比较两个排序的字符串。
compareTo() 的返回值是 int, 它是先比较对应字符的大小( ASCII 码顺序)
- 如果字符串相等返回值0
- 如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值前字符串的值小于后字符串,正值前字符串大于后字符串)
- 如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度.
对于 [830,8301],若纯粹使用 compareTo 方法无法得到正确解。 技巧在于先将两个字符串以不同的两种方式( right-to-left 或 left-to-right)连接后,再比较它们的大小。
class Solution {
//本题最好的方式采用字符串排序的方式
public String largestNumber(int[] nums) {
if(nums.length<=0){
return null;
}
String[] strs = new String[nums.length];
for (int i = 0; i < nums.length; i++) {
strs[i] = String.valueOf(nums[i]);
}
Arrays.sort(strs,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
//return o1.compareTo(o2); //这是正常的排序
String leftRight = o1+o2;
String rightLeft = o2+o1;
return -leftRight.compareTo(rightLeft);
}
});
StringBuilder sb = new StringBuilder();
for (String str : strs) {
System.out.print(str+" ");
sb.append(str);
}
while(sb.length()>1 && sb.charAt(0)=='0'){
sb.deleteCharAt(0);
}
return sb.toString();
}
}
#method
(这是错误的!!!)思路:建立一棵字典树 trie 比如:
我们可以把这一组数构建一棵字典树
字典树相当于二叉树的复杂版本
同时我们可以构建字典树的同时统计词的词频
构造好字典树后,我们采用遍历的方式来获取词以及词频,输出的数正好是我们需要的顺序
上代码:
class TreeNode{
int val;
int freq = 0; //统计词频
int MAX_SIZE = 10;
TreeNode[] digits;
TreeNode(int x){
this.val = x;
digits = new TreeNode[MAX_SIZE]; //对象默认赋值为空
}
}
class Trie{
TreeNode root;
Trie(){
root = null;
}
public void insertOneInteger(int num){
if(root == null){
root = new TreeNode(-1);
}
TreeNode cur = root;
int[] arr = int2Arr(num);
for (int i = 0; i < arr.length; i++) {
if(cur.digits[arr[i]]==null){
cur.digits[arr[i]] = new TreeNode(arr[i]); //不为空,则建一个节点
}
cur = cur.digits[arr[i]];
if(i == arr.length-1){ //统计单词的词频
cur.freq+=1;
}
}
}
public void buildTrie(int[] nums){ //构建字典树
for (int i = 0; i < nums.length; i++) {
insertOneInteger(nums[i]);
}
}
public void PreOrderTravelse(TreeNode root){ //优先遍历我们的字典树
if(root == null){
return;
}else{
System.out.print(root.val + "=="+root.freq+" ");
for (int i = 0; i < root.MAX_SIZE; i++) {
PreOrderTravelse(root.digits[i]);
}
}
}
public ArrayList<ArrayList<Integer>> LevelOrderTravelse(TreeNode root){ //层序遍历我们的字典树
ArrayList<ArrayList<Integer>> arrs = new ArrayList<>();
if(root == null){
return arrs;
}
ArrayList<Integer> arr = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
Queue<Integer> queLevel = new LinkedList<>();
que.add(root);
queLevel.add(0);
int level = 0;
while(que.size()>0){
if(queLevel.peek()>level){ //说明进入下一层了
arrs.add(arr);
arr = new ArrayList<>();
arr.add(que.peek().val);
}else{
arr.add(que.peek().val);
}
for (int i = 0; i < root.MAX_SIZE; i++) {
if(que.peek().digits[i]!=null){
que.add(que.peek().digits[i]);
queLevel.add(queLevel.peek()+1);
}
}
level = queLevel.peek();
que.poll();
queLevel.poll();
}
arrs.add(arr);
return arrs;
}
private int[] int2Arr(int num){ //将一个整数转换为数组
int[] arr = new int[intLen(num)];
int count = intLen(num)-1;
while(num>0){
arr[count] = num%10;
num /= 10;
count--;
}
return arr;
}
private int intLen(int num){ //求一个整数的长度
if(num<0){
return 0;
}
if(num == 0){
return 1;
}
int count = 0;
while(num>0){
num/=10;
count++;
}
return count;
}
public int depth(TreeNode root){
return LevelOrderTravelse(root).size();
}
public ArrayList<String> TrieTreePath(TreeNode root){ //取出我们词 遍历
ArrayList<String> paths = new ArrayList<>();
if(root == null){ //这一层是根节点
return paths;
}
helper(root,"",paths);
return paths;
}
private void helper(TreeNode root,String path,ArrayList<String> paths){
boolean flag = true;
for (int i = 0; i < root.MAX_SIZE; i++){
flag = (flag&& (root.digits[i] == null));
}
if(flag == true){ //说明到了叶子节点
paths.add(path+"|"+root.freq);
return;
}
if(root!= null && (root.freq>0)){ //其中某个节点词频 > 0 也需要把路径加入到paths
paths.add(path+"|"+root.freq);
}
for (int i = root.MAX_SIZE-1; i >=0; i--) {
if(root.digits[i]!=null){
helper(root.digits[i],path+root.digits[i].val,paths);
}
}
}
//将词频字符串转换为长整数
public String getLongInteger(ArrayList<String> arrs){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arrs.size(); i++) {
String arr = arrs.get(i);
String[] splits = arr.split("\\|");
int count = Integer.parseInt(splits[1]);
for (int j = 0; j < count; j++) {
sb.append(splits[0]);
}
}
return sb.toString();
}
}
我们可以看出来字典树可以大大压缩数据,节省空间,大树据处理的利器