1、将数组排成最小的数:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323
public static String PrintMinNumber(int[] numbers) {
if (numbers == null && numbers.length == 0) {
return "";
}
List<Integer> list = new ArrayList<>();
for (int i = 0; i < numbers.length; i++) {
list.add(numbers[i]);
}
list.sort((a, b) -> (a + "" + b).compareTo(b + "" + a));
return list.toString();
}
public static void main(String[] args) {
int[] numbers = { 35, 34, 33 };
System.out.println(PrintMinNumber(numbers)); // [33, 34, 35]
}
2、连续正数序列:输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1-5,4-6和7-8
/**
* 以求和为9的所有连续序列为例,
* pSmall--指向正数序列的首
* pBig--指向正数序列的首尾
* pSum表示序列之和
* 开始pSmall=1,pBig=2,pSum=3<9
* 于是pBig向后移1,此时pSmall=1……pBig=3 pSum=6<9
* 于是pBig再向后移1,此时pSmall=1……pBig=4 pSum=10>9,序列需要删除一些数
* 于是pSmall-1,pSum=9,找到第一个满足条件的序列;
* 接着pBig+1,按照前面的方法继续查找满足条件的序列,直到pSmall等于(9+1)/2.
* (最小值都是9的一半,那么最大值肯定超过9的一半,所以二者加起来肯定是大于9,
* 所以只需要最小值小于(9+1)/2)
*/
/**
* 求连续子区间的数字和
*
* @param small
* @param big
* @return
*/
private static ArrayList<Integer> addFromSmallToBig(int small, int big) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = small; i <= big; i++) {
list.add(i);
}
return list;
}
/**
* 两个指针相互协作
*
* @param sum
* @return
*/
public static ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
if (sum <= 2) {
return list;
}
int small = 1;// 下标
int big = 2;// 下标
int curSum = small + big;
int mid = (sum + 1) / 2;
while (small < mid) {
// 每次判断一下是都大于了sum值了,大的话,那就只能减了,
// 减的话,那就直接放到small的下一位,然后进行判断
while (curSum > sum && small < mid) {
curSum -= small;
small++;
}
// 第一步判断是否相等,不不相等就持续变大big值,并加入到curSum中
if (curSum == sum) {
list.add(addFromSmallToBig(small, big));
}
// 以上都不符合,那就是sum的值很小了,继续加!
big++;
curSum += big;
}
return list;
}
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> list_3 = new ArrayList<>();
list_3 = FindContinuousSequence(9);
for (int i = 0; i < list_3.size(); i++) {
System.out.println(list_3.get(i));
}
/**
* [2, 3, 4]
* [4, 5]
*/
}
3、在一个数组中除了一个数字只出现一次之外,其他数字都出现了2次,请找出那个只出现了一次的数字。
要求:线性时间复杂度O(N),空间复杂度为O(1)(提示:位运算)
//相同数字异或结果是0,数组中的所有数字进行异或操作,结果就是唯一出现的那个数字
public static int singleNumberTwo(int[] nums) {
int temp = 0;
for (int i = 0; i < nums.length; i++) {
temp ^= nums[i];
}
return temp;
}
public static void main(String[] args) {
int[] two = { 1, 1, 2, 2, 3, 3, 4, 4, 7 };
System.out.println(singleNumberTwo(two)); //7
}
4、在一个数组中除了一个数字只出现一次之外,其他数字都出现了3次,请找出那个只出现了一次的数字。
要求:线性时间复杂度O(N),空间复杂度为O(1)
/**
* 思路:三个相同的数字异或之后还是本身
* 转换思路:如果一个数字出现三次,那么他的二进制表示的每一位(0或者1)也出现3次。
* 把所有出现3次的数字的二进制的每一位都分别相加,那么每一位的和都能被3整除!!!
*
* 该算法的时间复杂度为O(N),因为内层循环和后边的循环都是常数级别的时间复杂度。
* 空间复杂度O(1),因为数组长度为32的是常数级别的
*/
public static int singgleNumberThree(int[] nums) {
int[] ints = new int[32];
for (int i = 0; i < nums.length; i++) {
int falg = 1;
for (int j = 31; j >= 0; j--) {
int anInt = nums[i] & falg;
if (anInt != 0)
ints[j] += 1;
falg = falg << 1;
}
}
int num = 0;
for (int i = 0; i < 32; i++) {
ints[i] = ints[i] % 3;
num += ints[i] * Math.pow(2, 31 - i);
}
return num;
}
public static void main(String[] args) {
int[] three = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 7 };
System.out.println(singgleNumberThree(three)); // 7
}