第26题
题目描述:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
分析:
方法一:递归
如上图所示,分为abc和abb演示,分别代表没有重复和有重复的情况。
代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList list = new ArrayList<String>();
if(str!=null && str.length()>0){
PermutationHelper(str.toCharArray(),0,list);
Collections.sort(list);
}
return list;
}
//增强的方法
public void PermutationHelper(char[] chars,int i,ArrayList<String> list){
//递归结束的条件
if(i == chars.length-1){
list.add(String.valueOf(chars));
}else{
//用于校验当前需要交换的元素是否重复
Set<Character> set = new HashSet<Character>();
for(int j=i;j<chars.length;j++){
if(!set.contains(chars[j])){
set.add(chars[j]);
swap(chars,i,j);
PermutationHelper(chars,i+1,list);
swap(chars,i,j);
}
}
}
}
//交换数组两个位置的元素
public void swap(char[] chars,int i,int j){
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
方法二:字典序法
如果知道字典序,这道题的解也非常简单,也不用考虑是否有重复的情况。定义如下:
故代码如下:
//字典序法就全排列
public ArrayList<String> Permutation2(String str){
ArrayList<String> list = new ArrayList<>();
//判断传入参数是否合法
if(str == null || str.length()<=0){
return list;
}
//字符串转为数组
char[] chars = str.toCharArray();
//对数组内的内容排序
Arrays.sort(chars);
//将第一个序列加到list中(数组转为字符串)
list.add(Arrays.toString(chars));
int len = chars.length;
while(true){
int leftIndex = len -1;
int rightIndex ;
/**
* find: j=max {i | Pi < Pi+1 }
* k=max {i | Pi > Pj }
*/
while(leftIndex>=1 && chars[leftIndex-1]>=chars[leftIndex]){
leftIndex--;
}
//此时leftIndex==0则没有下一个序列,跳出循环
if(leftIndex == 0)
break;
rightIndex = leftIndex ;
while(rightIndex<len && chars[rightIndex]>chars[leftIndex-1]){
rightIndex++;
}
swap(chars,leftIndex-1,rightIndex-1);
reverse(chars,leftIndex);
list.add(Arrays.toString(chars));
}
return list;
}
//倒置序列
private void reverse(char[] chars,int k){
if(chars==null || chars.length<=k)
return;
int len = chars.length;
for(int i=0;i<(len-k)/2;i++){
int m = k+i;
int n = len-1-i;
if(m<=n){
swap(chars,m,n);
}
}
}
//交换数组两个位置的元素
public void swap(char[] chars,int i,int j){
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
第二十七题:
题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
分析:
首先要处理数组,第一反应就是先排个序,上述数组变为{1,2,2,2,2,2,3,4,5}。
然后计算一下数组的一半是多少。
假如长度是10,则至少需要10/2+1=6个数字。
假如长度是9,则至少需要9/2+1=5个数字。(计算机中做除法不会保留小数部分)
故我们需要至少连续出现 数组长度/2 + 1 个相同的数,题目中说有一个这样的数,所有找到一个这样的数我们就可以直接返回。
代码如下:
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array.length == 1){
return array[0];
}
int len = (array.length/2)+1;
//对数组进行排序
Arrays.sort(array);
int value = 0;
int count = 1;
for(int i=0;i<array.length-1;i++){
if(array[i] == array[i+1]){
count++;
if(count>=len){
return value;
}
}else{
count = 1;
value = array[i+1];
}
}
return 0;
}
}
第二十八题:
题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
过于简单,不再分析。