Chp18: Hard

18.1 Write a function that adds two numbers. You should not use + or any arithmetic operators.

Solution: deal with 759 + 674.

1. add 759 + 674, but forget to carry. get 323

2. add 759 + 674, but only do the carrying, rather than the addition of each digit. get 1110

3. add the result of the first two operations(recursively): 1110 + 323 = 1433

1 public int add(int a, int b){
2     if(b == 0) return a;
3     if(a == 0) return b;
4     int sum = a ^ b; // 1
5     int ope = (a & b) << 1; // 2
6     return add(sum, ope);
7 }

18.3 Write a method to randomly generate a set of m integers from an array of size n. Each element must have equal probability of being chosen.

Solution: shrink the array to no longer contain elements that already chosen.

 1 public int[] pickMRandomly(int[] original, int m){
 2     int[] result = new int[m];
 3     int array = original.clone(); // 必须要先复制出来,否则会更改原来数组的结构
 4     for(int j = 0; j < m; j ++){
 5         int index = random(j, array.length - 1);
 6         result[j] = array[index];
 7         array[index] = array[j];
 8     }
 9     return result;
10 }

18.6 Describe an algorithm to find the smallest one million numbers in one billion numbers. Assume that the computer memory can hold all one billion numbers.

 Selection Rank Algorithm: find the ith smallest (or largest) element in an array in linear time.

If the elements are unique, can find it in O(n).

1.pick a random element in the array and use it as a "pivot". Partition elements around the pivot, keep track of the number of elements on the left side of the partition.

2.if there are exactly i elements on the left, then you just return the biggest element on the left.

3.if the left side is bigger than i, repeat the algo on just the left part of the array.

4.if the left side is smaller than i, repeat the algo on the right, but look for the lement with rank i - leftsize.

 1 public int partition(int[] array, int left, int right, int pivot){
 2     while(true){
 3         while(left <= right && array[left] <= pivot) left ++;
 4         while(left <= right && array[right] > pivot) right --;
 5         if(left > right) return left - 1;
 6         swap(array, left, right);
 7     }
 8 }
 9 public int rank(int[] array, int left, int right, int rank){
10     int pivot = array[randomIntInRange(left, right)];
11     int leftEnd = partition(array, left, right, pivot);
12     int leftSize = leftEnd - left + 1;
13     if(leftSize == rank + 1) return max(array, left, leftEnd);
14     else if(rank < leftSize) return rank(array, left, leftEnd, rank);
15     else return rank(array, leftEnd + 1, right, rank - leftSize);
16 }
原文地址:https://www.cnblogs.com/reynold-lei/p/3462399.html