zoukankan      html  css  js  c++  java
  • 剑指offer第二版-3.数组中重复的数

    面试题3:数组中重复的数

    题目要求:
    在一个长度为n的数组中,所有数字的取值范围都在[0,n-1],但不知道有几个数字重复或重复几次,找出其中任意一个重复的数字。

    解法比较:

    /**
     * Copyright(C) 2019 Hangzhou Differsoft Co., Ltd. All rights reserved.
     *
     */
    package com.java.offer;
    
    /**
     * 一个长度为n的数组,值的范围在0~n-1内,有一个或多个数字重复,求其中任意一个
     * 
     * @since 2019年1月29日 下午3:46:06
     * @author xuchao
     *
     */
    public class P3_DuplicationInArray {
    
        // 方法一:暴力求解,不会修改原始数据,时间复杂度o(n^2),空间复杂度o(1)
        public static int getDuplication1(int[] data) {
            if (data == null || data.length < 2) {
                return -1;
            }
            for (int i = 0; i < data.length - 1; i++) {
                for (int j = i + 1; j < data.length; j++) {
                    if (data[j] == data[i]) {
                        return data[j];
                    }
                }
            }
            return -1;
        }
        /**
         * 方法二:排序(使用快排),会修改原始数据,时间复杂度o(nlogn),空间复杂度o(1)
         * 1.使用内置排序(双轴快排),Arrays.sort(data)
         * 2.自己手写快排
         */
        public static int getDuplication2(int[] data) {
            if (data == null || data.length < 2) {
                return -1;
            }
            // 可以使用内置排序(双轴快排)
            // Arrays.sort(data);
            quickSort(data, 0, data.length - 1);
            for (int i = 0; i < data.length - 1; i++) {
                if (data[i + 1] == data[i]) {
                    return data[i + 1];
                }
            }
            return -1;
        }
    
        public static void quickSort(int[] data, int start, int end) {
            if (start >= end) {
                return;
            }
            int mid = partition(data, start, end);
            quickSort(data, start, mid - 1);
            quickSort(data, mid + 1, end);
        }
    
        public static int partition(int[] data, int start, int end) {
            int base = data[start];
            int i=start,j=end;
            while (i < j) {
                while (i < j && data[j] >= base) {
                    j--;
                }
                while (i < j && data[i] <= base) {
                    i++;
                }
                if (i < j) {
                    int t = data[i];
                    data[i] = data[j];
                    data[j] = t;
                }
            }
            data[start] = data[j];
            data[j] = base;
            return j;
        }
    
        // 方法三:借助哈希表,不会修改原始数据,时间复杂度o(n),空间复杂度o(n)
        public static int getDuplication3(int[] data) {
            if (data == null || data.length < 2) {
                return -1;
            }
            int[] a = new int[data.length];
            for (int t : data) {
                if (a[t] == 1) {
                    return t;
                } else {
                    a[t] = 1;
                }
            }
            return -1;
        }
    
        // 方法四:根据数字特点排序,会修改原始数据,时间复杂度o(n),空间复杂度o(1)
        public static int getDuplication4(int[] data) {
            if (data == null || data.length < 2) {
                return -1;
            }
            for (int i = 0; i < data.length; i++) {
                while (data[i] != i) {
                    if (data[i] == data[data[i]]) {
                        return data[i];
                    } else {
                        int temp = data[i];
                        data[i] = data[temp];
                        data[temp] = temp;
                    }
                }
            }
            return -1;
        }
    
        public static void main(String[] args) {
            int[] data1 = { 2, 5, 6, 4, 6, 3, 1 };
            // 不修改原始数据
            System.out.println(getDuplication1(data1));
            System.out.println(getDuplication3(data1));
    
            int[] data2 = { 2, 5, 6, 4, 6, 3, 1 };
            System.out.println(getDuplication2(data2));
            
            int[] data3 = { 4, 3, 5, 1, 5, 0 };
            System.out.println(getDuplication4(data3));
        }
    }
  • 相关阅读:
    Python 列表浅拷贝与深拷贝
    Linux 基本命令-----常用操作分类
    硬盘的分区方式
    github中fork的使用
    大O记号
    python的__file__和__name__变量
    python生成器
    python装饰器
    re模块元字符
    python_数据类型_list
  • 原文地址:https://www.cnblogs.com/chao-zjj/p/10370190.html
Copyright © 2011-2022 走看看