Java基础复习
- Java数组的声明与初始化
- Java ArrayList
- Java HashMap
- Java String 类
- Java LinkedList
- Java Deque继承LinkedList
- Java Set
- Java 队列
- 优先队列!!!
- Java数组划分
- Java数组转ArrayList
- String 转数字
- String
第一题:187. 重复的DNA序列
还是比较简单的:
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
List<String> results = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
for(int i=0; i+10<=s.length(); i++){
String subs = s.substring(i, i+10);
map.put(subs, map.getOrDefault(subs, 0)+1);
}
for(String tmp: map.keySet()){
if(map.get(tmp)>=2){
results.add(tmp);
}
}
return results;
}
}
第二道:219. 存在重复元素 II
最简单就是一个二重循环,但是嗯,还是想要自己想一想滑动窗口怎么写出来。
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
//固定窗口大小
for(int m=1; m<=k; m++){
for(int i=0; i+m<nums.length; i++){
if(nums[i]==nums[i+m]){
return true;
}
}
}
//暴力解法
// for(int i=0; i<nums.length; i++){
// for(int j=i+1; j<nums.length&&j<=i+k; j++){
// if(nums[i]==nums[j]){
// return true;
// }
// }
// }
return false;
}
}
但我觉得两者在正常情况下时间复杂度一样啊。
真无语,看题解,用得到哈希表。
真正有用的还是set,map,优先队列这种包装好的数据结构啊!!!
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
int n = nums.length;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < n; i++) {
if (i > k) set.remove(nums[i - k - 1]);
if (set.contains(nums[i])) return true;
set.add(nums[i]);
}
return false;
}
}
第三题:658. 找到 K 个最接近的元素
个人觉得优先队列就是万能的神!!
class Solution {
static Comparator<List<Integer>> cmp = new Comparator<List<Integer>>() {
public int compare(List<Integer> e1, List<Integer> e2) {
if(e1.get(0) - e2.get(0)==0){
return e1.get(2) - e2.get(2);
}
return e1.get(0) - e2.get(0);
}
};
public List<Integer> findClosestElements(int[] arr, int k, int x) {
//优先队列
List<Integer> results = new ArrayList<>();
Queue<List<Integer>> q = new PriorityQueue<>(cmp);
for(int i=0; i<arr.length; i++){
List<Integer> tmp = new ArrayList<>();
tmp.add(Math.abs(arr[i]-x));
tmp.add(arr[i]);
tmp.add(i);
q.offer(tmp);
}
for(int i=0; i<k; i++){
results.add(q.poll().get(1));
}
Collections.sort(results);
return results;
}
}
官方直接用原数组排序代码也很优雅。还有一种双指针+二分查找的方法!(分为两拨,一波<x,一波>x,然后在两拨找答案)。比我写得优雅太多了。
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> list = new ArrayList<Integer>();
for (int num : arr) {
list.add(num);
}
Collections.sort(list, (a, b) -> {
if (Math.abs(a - x) != Math.abs(b - x)) {
return Math.abs(a - x) - Math.abs(b - x);
} else {
return a - b;
}
});//lambda表达式
List<Integer> ans = list.subList(0, k);
Collections.sort(ans);
return ans;
}
}
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
int right = binarySearch(arr, x);
int left = right - 1;
while (k-- > 0) {
if (left < 0) {
right++;
} else if (right >= arr.length) {
left--;
} else if (x - arr[left] <= arr[right] - x) {
left--;
} else {
right++;
}
}
List<Integer> ans = new ArrayList<Integer>();
for (int i = left + 1; i < right; i++) {
ans.add(arr[i]);
}
return ans;
}
public int binarySearch(int[] arr, int x) {
int low = 0, high = arr.length - 1;
while (low < high) {
int mid = low + (high - low) / 2;
if (arr[mid] >= x) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}
}
第四题:718. 最长重复子数组
及其暴力的方法,必然超时。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
//原本的思路是短的数组直接怼上去一个一个对。现在发现起始位置不一定是0啊。
int[] mi = nums1.length<=nums2.length? nums1:nums2;
int[] ma = nums1.length<=nums2.length? nums2:nums1;
System.out.println(Arrays.toString(ma));
System.out.println(Arrays.toString(mi));
int res=0, tmp=0;
for(int k=mi.length; k>=0; k--){
for(int s=0; s+k<=mi.length; s++){
for(int i=0; i+k<=ma.length; i++){
tmp=0;
for(int j=s; j<s+k; j++){
System.out.print(j);
System.out.print(" ");
System.out.print(i+j-s);
System.out.print(" ");
if(mi[j]!=ma[i+j-s]){
res = Math.max(tmp, res);
tmp = 0;
}else{
tmp++;
}
System.out.println(tmp);
}
res = Math.max(tmp, res);
if(res>=k){
return res;
}
}
}
}
return res;
}
}
看了题解才明白,自己原来的贴贴法,再改进一下就有啦
具体参考题解:https://leetcode.cn/problems/maximum-length-of-repeated-subarray/solutions/28583/wu-li-jie-fa-by-stg-2
就是好厉害呀!
class Solution {
public int findLength(int[] A, int[] B) {
return A.length <= B.length ? findMax(A, B) : findMax(B, A);
}
private int findMax(int[] A, int[] B) {
int m = A.length, n = B.length;
int max = 0;
/*
A: |*|*|*|*|
B: |*|*|*|*|*|*|
↓
A: |*|*|*|*|
B: |*|*|*|*|*|*|
*/
for (int len = 1; len < m; len++) {
max = Math.max(max, find(A, B, 0, n - len, len));
}
/*
A: |*|*|*|*|
B: |*|*|*|*|*|*|
↓
A: |*|*|*|*|
B: |*|*|*|*|*|*|
*/
for (int j = n - m; j >= 0; j--) {
max = Math.max(max, find(A, B, 0, j, m));
}
/*
A: |*|*|*|*|
B: |*|*|*|*|*|*|
↓
A: |*|*|*|*|
B: |*|*|*|*|*|*|
*/
for (int len = m - 1; len > 0; len--) {
max = Math.max(max, find(A, B, m - len, 0, len));
}
return max;
}
private int find(int[] A, int[] B, int i, int j, int len) {
int max = 0, count = 0;
for (int k = 0; k < len; k++) {
if (A[i + k] == B[j + k]) {
count++;
} else {
max = Math.max(max, count);
count = 0;
}
}
return Math.max(max, count);
}
}
还有几题困难题,等全部结束再来。以上个人感觉都是非常有趣的题目。