1.认识复杂度和简单排序算法 | 左程云算法笔记

205 阅读2分钟

选择排序

在第一轮中把第一个元素假设为较小的元素,用第一个元素和后面的元素一个一个的比较,若被比较的元素较小时则交换它们的位置

在第二轮中,因为第一个元素在第一轮比较完后,它就是最小的元素了,所以把第二个元素假设为较小的元素,用第二个元素和后面的元素一个一个的比较,若被比较的元素较小时则交换它们的位置

一直最后一轮的倒数第二个元素和最后一个元素比较

class Solution {
    public int[] sortArray(int[] nums) {
        for (int i = 0; i < nums.length - 1; i++) {
            int min = i;
            for (int j = i+1; j < nums.length; j++){
                if (nums[j] < nums[min]) {
                   nums[j] = nums[j] ^ nums[min];
                   nums[min] = nums[j] ^ nums[min];
                   nums[j] = nums[j] ^ nums[min];
                }
            }

        }
        //[1,2,3,5]
        return nums;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{5,2,3,1};
        solution.sortArray(nums);
    }
}

冒泡排序

每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。

而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,将较大的数放后面,比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,重复此步骤,直到最后一个还没归位的数。

class Solution {
    public int[] sortArray(int[] nums) {
        if (nums == null || nums.length < 2) return nums;
        for (int i = 0; i < nums.length - 1; i++) {
            boolean isSorted  = true;//有序标记,每一轮的初始是true
            for (int j = 0; j < nums.length - 1 -i; j++){
                if (nums[j] > nums[j+1]) {
                   nums[j] = nums[j] ^ nums[j+1];
                   nums[j+1] = nums[j] ^ nums[j+1];
                   nums[j] = nums[j] ^ nums[j+1];
                   isSorted  = false;
                }
            }
            //一趟下来是否发生位置交换,如果没有交换直接跳出大循环
            if(isSorted )
                break;
        }
        return nums;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{5,2,3,1};
        solution.sortArray(nums);
    }
}

插入排序

(1)从第一个元素开始,该元素可以认为已经被排序。

(2)取出下一个元素,在已经排序的元素序列中从后向前扫描。

(3)如果该元素(已排序)大于新元素,则将该元素移动到下一个位置。

(4)重复上一个步骤,直到找到已排序的元素小于或者等于新元素的位置,将新元素插入到该位置后,重复上面的步骤。

class Solution {
    public int[] sortArray(int[] nums) {
       if (nums == null || nums.length < 2) return nums;
        for (int i = 1; i < nums.length; i++) {
            for (int j = i - 1; j >= 0; j--){
                if (nums[j] > nums[j+1]){
                    nums[j] = nums[j] ^ nums[j+1];
                    nums[j+1] = nums[j] ^ nums[j+1];
                    nums[j] = nums[j] ^ nums[j+1];
                }else break;
            }
        }
        return nums;
    }

   
}

异或运算

1.在一个整数数组中,有一个数出现了奇数次,其他数出现了偶数次,每个数都不相等,怎么找到出现奇数次的数?

class Solution {
   public int process(int[] arr){
       int result = 0;
       for (int i : arr) {
           result ^= i;
       }
       return result;
   }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{1,1,1,2,2};
        System.out.println(solution.process(nums));
    }
}

2.在一个整数数组中,有两个数出现了奇数次,其他数出现了偶数次,每个数都不相等,怎么找到出现奇数次的数?

class Solution {
   public List<Integer> process(int[] arr){
       List<Integer> result = new ArrayList<>();
//       设所求的两个数为a,b
       int eor = 0;
       for (int i : arr) {
           eor ^= i;
       }
       int eor2 = eor;
//       此时eor = a ^ b; eor1为eor二进制中最右侧的1,其他位为0;
       int eor1 = eor & (~ eor + 1);

       for (int i : arr) {
//           偶数次的数不用管,因为异或必为0,对结果无影响。此判断只会异或a,b中的一个,所以最后eor为a,b中的一个数;
           if ((eor1 & i) != 0) eor ^= i;
       }
//       算出另一个数
       int eor3 = eor2 ^ eor;
       result.add(eor);
       result.add(eor3);

       return result;
   }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{1,1,1,2,2,2,3,3};
        System.out.println(solution.process(nums));
    }
}