2021-03-22力扣刷题

文章目录

    • 编号217存在重复元素
      • HashMap解法,统计数组中每个数字出现的次数
      • 直接用HashSet去重,速度更快
    • 编号705设计哈希集合
    • 编号215数组中第K个最大元素
      • 利用最大堆的解法
    • 编号692前k个高频单词
      • 利用大顶堆,自定义构造器
      • 小顶堆解法,自定义构造器,先按需求反着来,限制堆大小为k,最后将结果顺序反转
    • 编号141环形链表
      • 快慢指针解法,当某一瞬间相遇时说明存在环
    • 编号881救生艇

编号217存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

示例 1:

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

输入: [1,2,3,4]
输出: false
示例 3:

输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

HashMap解法,统计数组中每个数字出现的次数

package lk2021_03_22;

import java.util.HashMap;

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

		HashMap<Integer, Integer> map = new HashMap<>();
		for (int i = 0; i < nums.length; i++) {
			if(!map.containsKey(nums[i])) {
				map.put(nums[i], 1);
			}else {
				int temp = map.get(nums[i]);
				map.put(nums[i], temp+1);
			}
		}
		
		for (int i = 0; i < nums.length; i++) {
			if(map.get(nums[i])>1) {
				return true;
			}
		}
		return false;
    }
}

直接用HashSet去重,速度更快

package lk2021_03_22;

import java.util.HashSet;

public class Main4 {

	public boolean containsDuplicate(int[] nums) {
		HashSet<Integer> set = new HashSet<>();
		for (int i = 0; i < nums.length; i++) {
			set.add(nums[i]);
		}
		return set.size()!=nums.length;
	}
}

编号705设计哈希集合

不使用任何内建的哈希表库设计一个哈希集合(HashSet)。

实现 MyHashSet 类:

void add(key) 向哈希集合中插入值 key 。
bool contains(key) 返回哈希集合中是否存在这个值 key 。
void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。

示例:

输入:
[“MyHashSet”, “add”, “add”, “contains”, “contains”, “add”, “contains”, “remove”, “contains”]
[[], [1], [2], [1], [3], [2], [2], [2], [2]]
输出:
[null, null, null, true, false, null, true, null, false]

解释:
MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1); // set = [1]
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(1); // 返回 True
myHashSet.contains(3); // 返回 False ,(未找到)
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(2); // 返回 True
myHashSet.remove(2); // set = [1]
myHashSet.contains(2); // 返回 False ,(已移除)

提示:

0 <= key <= 106
最多调用 104 次 add、remove 和 contains 。

进阶:你可以不使用内建的哈希集合库解决此问题吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/design-hashset
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:建立一个key范围的boolean数组,所有操作变成对数组的布尔值操作

class MyHashSet {

    /** Initialize your data structure here. */
    boolean[] hash;
    public MyHashSet() {
        hash = new boolean[1000001];
    }
    
    public void add(int key) {
        if(hash[key]==false){
            hash[key]=true;
        }
    }
    
    public void remove(int key) {
        if(hash[key]){
            hash[key]=false;
        }
    }
    
    /** Returns true if this set contains the specified element */
    public boolean contains(int key) {
        if(hash[key]){
            return true;
        }
        return false;
    }
}

/**
 * Your MyHashSet object will be instantiated and called as such:
 * MyHashSet obj = new MyHashSet();
 * obj.add(key);
 * obj.remove(key);
 * boolean param_3 = obj.contains(key);
 */

编号215数组中第K个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

利用最大堆的解法

package lk2021_03_22;

import java.util.Collections;
import java.util.PriorityQueue;

public class Main5 {
	public int findKthLargest(int[] nums, int k) {
		//最大堆
		PriorityQueue<Integer> heap = new PriorityQueue<>(Collections.reverseOrder());
		for (int i = 0; i < nums.length; i++) {
			heap.add(nums[i]);
		}
		while (k>1) {
			heap.poll();
			k--;
		}
		return heap.peek();
	}
}

编号692前k个高频单词

给一非空的单词列表,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:

输入: [“i”, “love”, “leetcode”, “i”, “love”, “coding”], k = 2
输出: [“i”, “love”]
解析: “i” 和 “love” 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 “i” 在 “love” 之前。

示例 2:

输入: [“the”, “day”, “is”, “sunny”, “the”, “the”, “the”, “sunny”, “is”, “is”], k = 4
输出: [“the”, “is”, “sunny”, “day”]
解析: “the”, “is”, “sunny” 和 “day” 是出现次数最多的四个单词,
出现次数依次为 4, 3, 2 和 1 次。

注意:

假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
输入的单词均由小写字母组成。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

利用大顶堆,自定义构造器

package lk2021_03_22;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.PriorityQueue;

public class Main6 {

	public List<String> topKFrequent(String[] words, int k) {
		HashMap<String, Integer> map = new HashMap<>();
		for (int i = 0; i < words.length; i++) {
			if(map.containsKey(words[i])) {
				int temp =map.get(words[i]);
				map.put(words[i], temp+1);
			}
			else {
				map.put(words[i], 1);
			}
		}
		//频数越大,字母越小的越在堆顶
		PriorityQueue<String> heap = new PriorityQueue<>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				// TODO 自动生成的方法存根
				return map.get(o1)==map.get(o2) ? o1.compareTo(o2) : -(map.get(o1)-map.get(o2));
			}
		});
		
		for(String word:map.keySet()) {
			heap.add(word);
		}
		List<String> res = new ArrayList<String>();
		while(k>0) {
			res.add(heap.poll());
			k--;
		}
		return res;
	}
}

小顶堆解法,自定义构造器,先按需求反着来,限制堆大小为k,最后将结果顺序反转

package lk2021_03_22;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.PriorityQueue;

public class Main7 {
	public List<String> topKFrequent(String[] words, int k) {
		HashMap<String, Integer> map = new HashMap<>();
		for(String word:words) {
			if(map.containsKey(word)) {
				int temp = map.get(word)+1;
				map.put(word, temp);
			}
			else {
				map.put(word, 1);
			}
		}
		
		//小顶堆,让比较情况和需要的情况反过来
		//频数越小越在堆顶,字母越大越先
		PriorityQueue<String> heap = new PriorityQueue<>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return map.get(o1)==map.get(o2)?o2.compareTo(o1):map.get(o1)-map.get(o2);
			}
		});
		for(String word:map.keySet()) {
			heap.add(word);
			if(heap.size()>k) {
				heap.poll();
			}
		}
		List<String> res = new ArrayList<String>();
		while (!heap.isEmpty()) {
			res.add(heap.poll());
		}
		//反转过来,字母越小的越先
		Collections.reverse(res);
		return res;
	}
}

编号141环形链表

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

示例 1:

2021-03-22力扣刷题_第1张图片

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
2021-03-22力扣刷题_第2张图片

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

快慢指针解法,当某一瞬间相遇时说明存在环

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null){
            return false;
        }
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null && fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast){
                return true;
            }
        }
        return false;
    }
}

编号881救生艇

第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。

每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。

返回载到每一个人所需的最小船数。(保证每个人都能被船载)。

示例 1:

输入:people = [1,2], limit = 3
输出:1
解释:1 艘船载 (1, 2)
示例 2:

输入:people = [3,2,2,1], limit = 3
输出:3
解释:3 艘船分别载 (1, 2), (2) 和 (3)
示例 3:

输入:people = [3,5,3,4], limit = 5
输出:4
解释:4 艘船分别载 (3), (3), (4), (5)
提示:

1 <= people.length <= 50000
1 <= people[i] <= limit <= 30000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/boats-to-save-people
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:先排序,再利用对撞双指针法,和两数之和有点类似的感觉,但提交后发现时间效率不算高

package lk2021_03_22;

import java.util.Arrays;

public class Main9 {

	public int numRescueBoats(int[] people, int limit) {
		//边界
		if(people==null||people.length==0) {
			return 0;
		}
		int res = 0;
		//先排序
		Arrays.sort(people);
		int l=0;
		int r=people.length-1;
		while (l<=r) {
			if(people[l]+people[r]<=limit) {
				l++;
			}
			r--;
			res+=1;
		}
		return res;
	}
}

你可能感兴趣的:(算法,力扣)