767.重构字符串
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab"
输出: "aba"
示例 2:
输入: S = "aaab"
输出: "
想到暴力搞了,定三参、前后判
PriorityQueue 优先队列自然排序
comparator 用法: 排序 使用场景
1.排序,需要比较两个对象谁排在前谁排在后(排序也可以让类实现Comparable接口,实现后该类的实例也具有排序能力)。
- 分组,需要比较两个对象是否是属于同一组。
class Solution {
public String reorganizeString(String S) {
if(S.length() < 2){
return S;
}
int[] counts = new int[26];
int maxCount = 0;
int length = S.length();
for(int i = 0; i < length; i++){
char c = S.charAt(i);
counts[c - 'a']++;
maxCount = Math.max(maxCount, counts[c - 'a']);
}
if(maxCount > (length + 1) / 2){
return "";
}
PriorityQueue<Character> queue = new PriorityQueue<Character>(new Comparator<Character>() {
public int compare(Character letterl, Character letterl2) {
return counts[letterl2 - 'a'] - counts[letterl - 'a'];
}
});
for(char c = 'a'; c <= 'z'; c++){
if(counts[c - 'a'] > 0){
queue.offer(c);
}
}
StringBuffer sb = new StringBuffer();
while(queue.size() > 1){
char letterl = queue.poll();
char letterl2 = queue.poll();
sb.append(letterl);
sb.append(letterl2);
int indexl = letterl - 'a', index2 = letterl2 - 'a';
counts[indexl]--;
counts[index2]--;
if(counts[indexl] > 0){
queue.offer(letterl);
}
if(counts[index2] > 0){
queue.offer(letterl2);
}
}
if(queue.size() > 0){
sb.append(queue.poll());
}
return sb.toString();
}
}
34.在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
方法一: 二分法
class Solution {
public int[] searchRange(int[] nums, int target) {
//binarySearch方法为二分法查找,所以数组必须是有序的或者是用sort()方法排序之后的。
int leftIdx = binarySearch(nums, target, true);
int rightIdx = binarySearch(nums, target, false) - 1;
if(leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target){
return new int[]{leftIdx, rightIdx};
}
return new int[]{-1, -1};
}
public int binarySearch(int[] nums, int target, boolean lower) {
int left = 0, right = nums.length -1, ans = nums.length;
while (left <= right) {
int mid = (left + right) / 2;
if(nums[mid] > target || (lower && nums[mid] >= target)){
right = mid - 1;
ans = mid;
} else {
left = mid + 1;
}
}
return ans;
}
}
321.拼接最大数
给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。
示例 1:
输入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
[9, 8, 6, 5, 3]
class Solution {
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
int m = nums1.length, n = nums2.length;
int[] maxSubsequence = new int[k];
int start = Math.max(0, k - n), end = Math.min(k, m);
for (int i = start; i <= end; i++) {
int[] subsequence1 = maxSubsequence(nums1, i);
int[] subsequence2 = maxSubsequence(nums2, k - i);
int[] curMaxSubsequence = merge(subsequence1, subsequence2);
if (compare(curMaxSubsequence, 0, maxSubsequence, 0) > 0) {
System.arraycopy(curMaxSubsequence, 0, maxSubsequence, 0, k);
}
}
return maxSubsequence;
}
public int[] maxSubsequence(int[] nums, int k) {
int length = nums.length;
int[] stack = new int[k];
int top = -1;
int remain = length - k;
for (int i = 0; i < length; i++) {
int num = nums[i];
while (top >= 0 && stack[top] < num && remain > 0) {
top--;
remain--;
}
if (top < k - 1) {
stack[++top] = num;
} else {
remain--;
}
}
return stack;
}
public int[] merge(int[] subsequence1, int[] subsequence2) {
int x = subsequence1.length, y = subsequence2.length;
if (x == 0) {
return subsequence2;
}
if (y == 0) {
return subsequence1;
}
int mergeLength = x + y;
int[] merged = new int[mergeLength];
int index1 = 0, index2 = 0;
for (int i = 0; i < mergeLength; i++) {
if (compare(subsequence1, index1, subsequence2, index2) > 0) {
merged[i] = subsequence1[index1++];
} else {
merged[i] = subsequence2[index2++];
}
}
return merged;
}
public int compare(int[] subsequence1, int index1, int[] subsequence2, int index2) {
int x = subsequence1.length, y = subsequence2.length;
while (index1 < x && index2 < y) {
int difference = subsequence1[index1] - subsequence2[index2];
if (difference != 0) {
return difference;
}
index1++;
index2++;
}
return (x - index1) - (y - index2);
}
}
204.计数质数
统计所有小于非负整数 n
的质数的数量。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
方法一:枚举
class Solution {
public int countPrimes(int n) {
int ans = 0;
for (int i = 2; i < n; ++i) {
ans += isPrime(i) ? 1 : 0;
}
return ans;
}
public boolean isPrime(int x) {
for (int i = 2; i * i <= x; ++i) {
if (x % i == 0) {
return false;
}
}
return true;
}
}
方法二:埃氏筛
class Solution {
public int countPrimes(int n) {
int[] isPrime = new int[n];
Arrays.fill(isPrime, 1);
int ans = 0;
for (int i = 2; i < n; ++i) {
if (isPrime[i] == 1) {
ans += 1;
if ((long) i * i < n) {
for (int j = i * i; j < n; j += i) {
isPrime[j] = 0;
}
}
}
}
return ans;
}
}
方法三:线性筛
class Solution {
public int countPrimes(int n) {
List<Integer> primes = new ArrayList<Integer>();
int[] isPrime = new int[n];
Arrays.fill(isPrime, 1);
for (int i = 2; i < n; ++i) {
if (isPrime[i] == 1) {
primes.add(i);
}
for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
isPrime[i * primes.get(j)] = 0;
if (i % primes.get(j) == 0) {
break;
}
}
}
return primes.size();
}
}
659.分割数组为连续子序列
给你一个按升序排序的整数数组 num
(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。
如果可以完成上述分割,则返回 true
;否则,返回 false
。
示例 1:
输入: [1,2,3,3,4,5]
输出: True
解释:
你可以分割出这样两个连续子序列 :
1, 2, 3
3, 4, 5
方法一:哈希表 + 最小堆
class Solution {
public boolean isPossible(int[] nums) {
Map<Integer, PriorityQueue<Integer>> map = new HashMap<Integer, PriorityQueue<Integer>>();
for (int x : nums) {
if (!map.containsKey(x)) {
map.put(x, new PriorityQueue<Integer>());
}
if (map.containsKey(x - 1)) {
int prevLength = map.get(x - 1).poll();
if (map.get(x - 1).isEmpty()) {
map.remove(x - 1);
}
map.get(x).offer(prevLength + 1);
} else {
map.get(x).offer(1);
}
}
Set<Map.Entry<Integer, PriorityQueue<Integer>>> entrySet = map.entrySet();
for (Map.Entry<Integer, PriorityQueue<Integer>> entry : entrySet) {
PriorityQueue<Integer> queue = entry.getValue();
if (queue.peek() < 3) {
return false;
}
}
return true;
}
}
方法二:贪心
class Solution {
public boolean isPossible(int[] nums) {
// Map.getOrDefault(Object key, V defaultValue)方法的作用是:
// 当Map集合中有这个key时,就使用这个key值;
// 如果没有就使用默认值defaultValue。
Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
Map<Integer, Integer> endMap = new HashMap<Integer, Integer>();
for(int x : nums){
int count = countMap.getOrDefault(x, 0) + 1;
countMap.put(x, count);
}
for(int x : nums){
int count = countMap.getOrDefault(x, 0);
if(count > 0){
int prevEndCount = endMap.getOrDefault(x - 1, 0);
if(prevEndCount > 0){
countMap.put(x, count - 1);
endMap.put(x - 1, prevEndCount - 1);
endMap.put(x, endMap.getOrDefault(x, 0) + 1);
} else {
int count1 = countMap.getOrDefault(x + 1, 0);
int count2 = countMap.getOrDefault(x + 2, 0);
if(count1 > 0 && count2 > 0){
countMap.put(x, count - 1);
countMap.put(x + 1, count1 - 1);
countMap.put(x + 2, count2 - 1);
endMap.put(x + 2, endMap.getOrDefault(x + 2, 0) + 1);
} else {
return false;
}
}
}
}
return true;
}
}
621.任务调度器
给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。
然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的 最短时间 。
示例 1:
输入:tasks = ["A","A","A","B","B","B"], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。
方法一:模拟
class Solution {
public int leastInterval(char[] tasks, int n) {
Map<Character, Integer> freq = new HashMap<Character, Integer>();
for (char ch : tasks) {
freq.put(ch, freq.getOrDefault(ch, 0) + 1);
}
// 任务总数
int m = freq.size();
List<Integer> nextValid = new ArrayList<Integer>();
List<Integer> rest = new ArrayList<Integer>();
Set<Map.Entry<Character, Integer>> entrySet = freq.entrySet();
for (Map.Entry<Character, Integer> entry : entrySet) {
int value = entry.getValue();
nextValid.add(1);
rest.add(value);
}
int time = 0;
for (int i = 0; i < tasks.length; ++i) {
++time;
int minNextValid = Integer.MAX_VALUE;
for (int j = 0; j < m; ++j) {
if (rest.get(j) != 0) {
minNextValid = Math.min(minNextValid, nextValid.get(j));
}
}
time = Math.max(time, minNextValid);
int best = -1;
for (int j = 0; j < m; ++j) {
if (rest.get(j) != 0 && nextValid.get(j) <= time) {
if (best == -1 || rest.get(j) > rest.get(best)) {
best = j;
}
}
}
nextValid.set(best, time + n + 1);
rest.set(best, rest.get(best) - 1);
}
return time;
}
}
方法二:构造
class Solution {
public int leastInterval(char[] tasks, int n) {
Map<Character, Integer> freq = new HashMap<Character, Integer>();
// 最多的执行次数
int maxExec = 0;
for (char ch : tasks) {
int exec = freq.getOrDefault(ch, 0) + 1;
freq.put(ch, exec);
maxExec = Math.max(maxExec, exec);
}
// 具有最多执行次数的任务数量
int maxCount = 0;
Set<Map.Entry<Character, Integer>> entrySet = freq.entrySet();
for (Map.Entry<Character, Integer> entry : entrySet) {
int value = entry.getValue();
if (value == maxExec) {
++maxCount;
}
}
return Math.max((maxExec - 1) * (n + 1) + maxCount, tasks.length);
}
}
118.杨辉三角
给定一个非负整数 *numRows,*生成杨辉三角的前 numRows 行。
方法一:数学
class Solution {
public List<List<Integer>> generate(int numRows) {
//迭代器
List<List<Integer>> ret = new ArrayList<List<Integer>>();
for(int i = 0; i < numRows; ++i){
List<Integer> row = new ArrayList<Integer>();
for(int j = 0; j <= i; ++j){
if(j == 0 || j == i){
row.add(1);
} else{
row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));
}
}
ret.add(row);
}
return ret;
}
}
作者:LeetCode-Solution
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。