LeetCode:多数元素、存在重复元素、有效的字母异位词、数组中的重复的数字、丢失的数字

多数元素

题目描述
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例:输入:[3,2,3] 输出:3

解法一:排序法

由题目可知,重复数字的个数一定比数组长度的一半还长,所以当对数组排好序之后,重复数字一定会出现在n/2的位置,所以输出这个位置上的数字就是重复数字(众数)

import java.util.Arrays;
import java.util.Scanner;

public class MajorityElement {
    public void majorityElement(int[] num,int n){
        Arrays.sort(num);
        System.out.println(num[n/2]);
    }
    public static void main(String[] args) {
//        怎么用到排序的思想呢?
//        向下取整是横杠在下面 向下取整就是取得更小
//        向上取整是横杠在上面 向上取整就是取得更大
//        其实题目的意思就是众数出现的个数一定会过半
//        那么如果此时将数组按顺序排好  那么众数一定会在中间出现
        MajorityElement obj=new MajorityElement();
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] num=new int[n];
        int i;
        for (i = 0; i < n; i++) {
            num[i]=input.nextInt();
        }
        obj.majorityElement(num,n);
    }
}


解法二:哈希表(还没搞定)


存在重复元素

题目描述
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例:输入:nums = [1,2,3,1] 输出:true

解法一:排序法

import java.util.Arrays;
import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

public class ContainsDuplicate {
    public boolean containsDuplicate(int[] nums){

//        排序法
        Arrays.sort(nums);
        int flag=0;
        for (int i = 0; i < nums.length-1; i++) {
            if (nums[i]==nums[i+1])
                return true;
        }
            return  false;
    }
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        ContainsDuplicate obj=new ContainsDuplicate();
        obj.containsDuplicate(nums);
        System.out.println(obj.containsDuplicate(nums));
    }
}


解法二:哈希表

import java.util.Arrays;
import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

public class ContainsDuplicate {
    public boolean containsDuplicate(int[] nums){
//        哈希表
//        int rand=0;
        Set<Integer> set = new HashSet<>();
        for (int num: nums) {
            if (set.contains(num)) {
                return true;
            }
            set.add(num);
        }
        return false;
    }
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        ContainsDuplicate obj=new ContainsDuplicate();
        obj.containsDuplicate(nums);
        System.out.println(obj.containsDuplicate(nums));
    }
}


解法三:去重法(和HashSet差不多,但是用到的方法不同)

若去重后数字(即不同数字)的个数不等于原数组的长度,返回true,说明有重复数字

import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.IntStream;
public class ContainsDuplicate {
    public boolean containsDuplicate(int[] nums){
       return IntStream.of(nums).distinct().count() != nums.length;
    }
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        ContainsDuplicate obj=new ContainsDuplicate();
        obj.containsDuplicate(nums);
        System.out.println(obj.containsDuplicate(nums));
    }
}



有效的字母异位词

题目描述
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例:输入: s = “anagram”, t = “nagaram” 输出: true

解法一:排序法

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;

public class IsAnagram {
    public boolean isAnagram(String s,String t){
//        若字符串长度不同先淘汰
        if (s.length()!=t.length())
            return false;
//        对字符串进行排序的方法
//        首先将字符串转成字符数组
//        这里可以对这个方法做一个说明和补充
        char[] string1=s.toCharArray();
        char[] string2=t.toCharArray();
        Arrays.sort(string1);
        Arrays.sort(string2);
        for (int i=0;i<s.length();i++){
            if (string1[i]!=string2[i])
                return false;
        }
        return true;
    }
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String s,t;
        s=input.next();
        t=input.next();
        IsAnagram obj=new IsAnagram();
        System.out.println(obj.isAnagram(s,t));
    }
}


解法二:哈希表

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;

public class IsAnagram {
    public boolean isAnagram(String s,String t){
if (s.length() != t.length()) {
            return false;
        }
        int[] table = new int[26];
        for (int i = 0; i < s.length(); i++) {
            table[s.charAt(i) - 'a']++;
        }
        for (int i = 0; i < t.length(); i++) {
            table[t.charAt(i) - 'a']--;
            if (table[t.charAt(i) - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String s,t;
        s=input.next();
        t=input.next();
        IsAnagram obj=new IsAnagram();
        System.out.println(obj.isAnagram(s,t));
    }
}


数组中的重复的数字

题目描述:找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1
的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例: 输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3

解法一:排序法

将数组排序之后,对数组进行遍历,只要遇到i和i+1的位置相同足以说明该数是重复的,此时输出即可(因为题目没要求统计重复次数以及输出所有的重复数字)

import java.util.Arrays;
import java.util.Scanner;

public class FindRepeatNumber {
    public int findRepeatNumber(int[] nums){
        Arrays.sort(nums);
        for (int i = 0; i < nums.length-1; i++) {
            if (nums[i]==nums[i+1])
                return nums[i];
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        FindRepeatNumber obj=new FindRepeatNumber();
        System.out.println(obj.findRepeatNumber(nums));
    }
}


解法二:哈希表

利用Set最大的功能:去重
一旦contains(num)返回true,说明已存在该数num,此时输出并退出即可
否则,将该数添加到哈希表中并继续遍历
具体步骤如下:
(1)初始化一个HashSet
(2)遍历数组nums的每个数字,当num存在于哈希表中,说明重复,直接返回num;否则将num添加至哈希表中

import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class FindRepeatNumber {
    public int findRepeatNumber(int[] nums){
//        哈希表
//        利用的是Set最大的功能就是去重
        Set<Integer> set=new HashSet<>();
        for (int num:nums) {
            if (set.contains(num)) return num;
            set.add(num);
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        FindRepeatNumber obj=new FindRepeatNumber();
        System.out.println(obj.findRepeatNumber(nums));
    }
}


多数元素

题目描述:给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例:
解法一:排序法

import java.util.Arrays;
import java.util.Scanner;

public class MisingNumber {
    public int missingNumber(int[] nums){
        
//        应该可以用set来写,利用去重的特性
//        排序法
        Arrays.sort(nums);
        int i=0,j=0;
        for (i=0;i<nums.length;i++){
            if (nums[i]!=i)
                return i;
        }
        return nums.length;
    }
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        MisingNumber obj=new MisingNumber();
        System.out.println(obj.missingNumber(nums));
    }
}


解法二:哈希表

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Scanner;

public class MisingNumber {
    public int missingNumber(int[] nums){
        //HashSet
        Set<Integer> set = new HashSet<>();
        int n=nums.length;
        int i,j;
        for (i = 0; i < n; i++) {
            set.add(nums[i]);
        }
        for (j = 0; j <=n; j++) {
            if (!set.contains(j))
                return j;
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        MisingNumber obj=new MisingNumber();
        System.out.println(obj.missingNumber(nums));
    }
}


解法三:数学公式

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Scanner;

public class MisingNumber {
    public int missingNumber(int[] nums){
        //数学做法
//        先算都存在的和
//        算缺失后的和
//        两者之差为缺失值
        int n=nums.length;
        int sum1=n*(n+1)/2;
        int sum2=0;
        for (int i = 0; i < n; i++) {
            sum2+=nums[i];
        }
        return sum1-sum2;
    }
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        int n;
        n=input.nextInt();
        int[] nums=new int[n];
        for (int i = 0; i < n; i++) {
            nums[i]=input.nextInt();
        }
        MisingNumber obj=new MisingNumber();
        System.out.println(obj.missingNumber(nums));
    }
}

总结

(1)由上面的这些题与题解可知,像这种寻找重复数(众数)、输出重复数等的这种统计问题,通用(常用、简单)的两种办法是利用排序和哈希表(其实也可以说是,可以用排序法的用哈希表也行)
(2)类似的题还有寻找重复数、删除排序数组中的重复项、只出现一次的数字、数组中出现的次数
(3)对Map、Set、HashSet、HasgMap不熟悉的通过这几道题,也能加深对其的理解
(4)这里的排序法,也可以使用冒泡排序、快速排序等这些方法,只是这里不强调这些,所以使用Arrays.sort(nums)


知识点补充

(1)Map和Set

Map的定义

Map中存储的是Key-Value的键值对,将键映射到值的对象,映射不能包含重复的键,每个键最多可以映射到一个值

Map的常见办法

方法 说明
v get(object k) 根据指定的k查找v
v getOrDefault(object k,v defaultValue) 根据指定的k查找对应的v,没有找到用默认值替代
v put(k key,v value) 将指定的k-v放入Map
boolean containsKey(object key) 断是否包含key
boolean containsValue(object value) 判断是否包含value
Set> entrySet() 将所有键值对返回
boolean isEmpty() 判断是否为空
int size() 返回键值对的数量
remove(object key) 删除key对应的映射关系
import java.util.HashMap;
import java.util.Set;

public class Map {
    public static void main(String[] args) {
        HashMap<String,String> map=new HashMap<String,String>();
//        1.使用put存放元素
        map.put("涩琪","red velvet");
        map.put("智秀","Blackpink");
        map.put("朴智旻","Promise");
        System.out.println(map);
//        2.使用get获取key对应的value
        String str1=map.get("涩琪");
        System.out.println(str1);
//        3.使用getOrDefault返回key对应的value
        String str2=map.getOrDefault("涩琪","77");
        System.out.println(str2);
//        4.使用remove删除key对应的映射关系
        map.remove("朴智旻");
        System.out.println(map);
//        5.使用KeySet返回Key的所有不重复集合
        Set<String> set=map.keySet();
        System.out.println(set);
//9.containsKey
        System.out.println(map.containsKey("智秀"));

        //6.containsValue
        System.out.println(map.containsValue("Blackpink"));

        //7.size
        System.out.println(map.size());

        //8.isEmpty
        System.out.println(map.isEmpty());
    }
}

Map的注意事项

(1)put是根据一个函数来存放的,并非按顺序存放
(2)Map不能存放相同的键,如果存放,则会更新为最新的value
(3)Map中的key,value均可以为null
(4)Map是一个接口,不能直接实例化对象,只能实例化TreeMap或者HashMap
(5)Map中存放键值对的key是唯一的,value是可以重复的

Set的定义

Set是继承来自Collection的接口类,Set中存放了Key

Set的常用方法

方法 说明
boolean add(E e) 如果set中尚未存在指定的元素,则添加此元素
boolean addAll(Collection c 如果set中没有指定collection中的所有元素,则将其添加到此set中
void clear() 移除此set中的所有元素
boolean contains(object o) 如果set包含指定的元素,则返回true
boolean containsAll(Collection c) 判断是否包含value
boolean equals(Object o) 比较指定对象与此set的相等性
int hashCode() 返回set的哈希值
boolean isEmpty() 如果set不包含元素,则返回true
Iterator iterator() 返回在此set中的元素进行迭代的迭代器
import java.util.HashSet;

public class Set {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        //1.add添加元素
        set.add("智秀");
        set.add("涩琪");
        set.add("朴智旻");
        System.out.println(set);

        //2.contains,判断是否包含元素
        System.out.println(set.contains("涩琪"));

        //3.删除集合中的元素
        System.out.println(set.remove("朴智旻"));
        System.out.println(set);

        //5.size,获取元素个数
        System.out.println(set.size());

        //6.isEmpty,判断是否为空
        System.out.println(set.isEmpty());

        //7.toArray
        Object [] array = set.toArray();
        for(int i = 0; i < array.length; i++){
            System.out.println(array[i]);
        }
    }
}

Set的注意事项

(1)Set的底层使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中 (2)Set最大的功能就是去重

哈希表getOrDefault()方法的使用

如果存在相应的key则返回其对应的value,否则返回给定的默认值;
比较两个哈希表中key对应的value值大小:如果其中一个哈希表中不存在某个key,那么两个hash表如何比较。
方法:
hash1.getOrDefault(c,0) < hash2.getOrDefault(c,0) //如果两个哈希表都有某个key值,那么他们比较的就是其中value的大小,若其中一个哈希表不存在某个key值,那么比较的就是其中的默认值。


(2)IntStream distinct()是java.util.stream.IntStream中的方法。此方法返回由不同元素组成的流。这是有状态的中间操作,即在处理新元素时,它可以合并先前看到的元素的状态。

//将数组中的数字都放入Integer流中
//nums也可被替换成具体的数字,例如2,3,4,5,....
IntStream.of(nums)
//取得Integer流中的不同元素
IntStream.of(nums).dintinct()
//计算流中不同元素的值(即个数)
IntStream.of(nums).dintinct().count()

(3) 向下取整是横杠在下面 向下取整就是取得更小;向上取整是横杠在上面 向上取整就是取得更大
(4)java中对字符串的排序是通过将字符串转成字符数组来实现的(具体的过程可以看有效的字母异位词里的代码)

你可能感兴趣的:(LeetCode,leetcode)