一、简单的难题
class Swap {
//不使用新的变量,交换两个变量的值
public static void main(String[] args) {
int a = 10;
int b = 20;
/*
异或算法(对称加密算法),一次异或:1010^0011 =1001 ,二次异或:1001^0011 =1010
原文^密钥 =密文 --> 密文还原成原文,二次异或; 密文^密钥 =原文
*/
//用密文做中间的量
//a是密文
a = a ^ b;
// a赋值给b,此时b已经成了a
b = a ^ b;
// b赋值给了a,此时完成交换
a = a ^ b;
System.out.println("a---->" + a);
System.out.println("b---->" + b);
}
}
二、谁能给我解释一下:为什么这段代码使用随机字符串打印出了 hello world?
当我们调用 Random 的构造方法时,给定了一个“种子”(seed)参数。比如本例子中的:-229985452 或 -147909649。
那么 Random 将从指定的种子值开始生成随机数。
而每个用相同的种子构造的 Random 对象,都会按照产生相同的模式产生数字。
public class MainTest {
public static void main(String[] args) {
System.out.println(randomString(-229985452) + " " + randomString(-147909649));
}
public static String randomString(int i) {
Random ran = new Random(i);
StringBuilder sb = new StringBuilder();
while (true) {
// nextInt(27) 限定了,当前返回的数 k 一定是在 [0,27) 之间的一个数字。
int k = ran.nextInt(27);
if (k == 0)
break;
// char 类型的强制转换。
// ` 对应ascii 码为 96,这个代码 '`' + k 的范围就是 [96+1,96+26],也就是 [97,122],即对应 ascii 码的 a-z。
sb.append((char) ('`' + k));
}
return sb.toString();
}
}
首先 new Random(-229985452).nextInt(27) 的前五个返回是这样的:
8
5
12
12
15
0
而 new Random(-147909649).nextInt(27) 的前五个返回是这样的:
23
15
18
12
4
0
所以,对照着 ascii 码表看,就能看出其对应的字母了:
8 + 96 = 104 --> h
5 + 96 = 101 --> e
12 + 96 = 108 --> l
12 + 96 = 108 --> l
15 + 96 = 111 --> o23 + 96 = 119 --> w
15 + 96 = 111 --> o
18 + 96 = 114 --> r
12 + 96 = 108 --> l
4 + 96 = 100 --> d
三、程序员招租联系方式
class PhoneUtil {
public static void main(String[] args) {
int[] arr = {3, 5, 1, 8, 7, 2};
int[] index = {2, 3, 0, 5, 5, 4, 1, 2, 0, 1, 0};
StringBuilder phoneNum = new StringBuilder();
for (int i : index) {
phoneNum.append(arr[i]);
}
System.out.println("联系方式:" + phoneNum);
}
}
四、睡眠排序
class SortUtil {
public static void main(String[] args) {
int[] nums = new int[]{1, 2, 34, 4, 45, 56};
sleepSort(nums);
}
/**
* 多线程同时睡眠排序大法
*
* @param nums int[]
*/
public static void sleepSort(int[] nums) {
for (final int num : nums) {
new Thread(() -> {
try {
Thread.sleep(num);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(num);
}).start();
}
}
}
五、猴子排序
class SortUtil {
public static void main(String[] args) {
int[] nums = new int[]{1, 2, 34, 4, 45, 56};
monkeySort(nums);
System.out.println(Arrays.toString(nums));
}
/**
* 艾米尔雷伯尔 在1909年的时候提出了打字的猴子的概念,他是说如果让一个猴子在电脑上随机的去敲打,时间足够长,那么一定可以打出一本莎士比亚全集
* 由此得出思路,对于数组而言,每次进行一个随机的排序,那么总有一次它能变成一个有序的数组,如果运气好,一次就搞定了,时间发杂度岂不是perfect,完美!
* @param nums int[]
*/
private static void monkeySort(int[] nums) {
//需要将nums打乱
List<Integer> tmp = Ints.asList(nums);
out:
while (true) {
Collections.shuffle(tmp);
int[] result = Ints.toArray(tmp);
//判断当前的集合或者数组是不是有序
for (int i = 0; i < result.length - 1; i++) {
if (result[i] > result[i + 1]) {
continue out;
}
}
// 证明了result是有序的,需要进行拷贝
System.arraycopy(result, 0, nums, 0, result.length);
break;
}
}
}
六、延时日期
class DateUtil {
public static void main(String[] args) {
Date tomorrow = getTomorrow(1);
System.out.println(tomorrow);
}
/**
* 获取明天的日期
* @param days 天数
* @return 明天的日期
*/
public static Date getTomorrow(int days) {
try {
Thread.sleep(24L *60*60*1000*days);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Date();
}
}
七、随机查找
class SearchUtil {
public static void main(String[] args) {
int[] nums = new int[]{1, 3, 6, 8, 4, 5, 7, 8, 9};
int index = randomSearch(nums, 8);
System.out.println(index);
}
//数组不有序,不用折半查找
public static int randomSearch(int[] nums, int target) {
for (; ; ) {
int randomIndex = (int) (Math.random() * nums.length);
if (target == nums[randomIndex]) {
return randomIndex;
}
}
}
}
八、乱序排列
//手动实现Collections.shuffle方法,不直接调用jdk的api,结合随机查找和猴子排序实现
class SortUtil {
public static void main(String[] args) {
int[] nums = new int[]{1, 2, 34, 4, 45, 56};
shuffle(nums);
System.out.println(Arrays.toString(nums));
}
/**
* 将数组乱序排列
*
* @param nums int[]
*/
public static void shuffle(int[] nums) {
// 新数组用来存储乱序的结果
int[] result = new int[nums.length];
int index = 0;
//创建一个备忘录
HashSet<Object> memo = new HashSet<>();
//随机获取一个值放到新的数组
for (; ; ) {
int randomIndex = (int) (Math.random() * nums.length);
if (memo.contains(randomIndex)) {
continue;
}
result[index++] = nums[randomIndex];
memo.add(randomIndex);
if (index == result.length) break;
}
System.arraycopy(result, 0, nums, 0, nums.length);
}
}
七、睡眠最值法
class SortUtil {
public static void main(String[] args) {
int[] nums = new int[]{1, 56, 2, 34, 4, 45};
int max = findMax(nums);
System.out.println(max);
}
// 寻找数组中的最大值
public static int findMax(int[] nums) {
//在INDEX返回之前让所有线程执行完毕,CountDownLatch线程同步工具
CountDownLatch countDownLatch = new CountDownLatch(nums.length);
for (int i = 0; i < nums.length; i++) {
//不能在lambda表示式中直接引用外边的变量,需要final修饰
final int j = i;
new Thread(() -> {
try {
Thread.sleep(nums[j]);
} catch (InterruptedException e) {
e.printStackTrace();
}
Result.INDEX = j;
//每次赋值结束后
countDownLatch.countDown();
}).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return Result.INDEX;
}
private static class Result {
// volatile 保证INDEX的有序性和可见性
private static volatile int INDEX = -1;
}
}