这是每次刷LeetCode时最先刷的专题,主要目的是练手熟悉刷题环境。
- 中等 无重复字符的最长子串 Longest Substring Without Repeating Characters
20.07.06
思路:用last记录上一次出现的位置。妙啊。其实本来想写HashMap的,可惜不会。滑动窗口倒是很有共识。
class Solution {
private int res = 0;
public int lengthOfLongestSubstring(String s) {
int[] last = new int[128];
for(int i=0;i<128;i++){
last[i] = -1;
}
int left = 0;
int n = s.length();
for(int i=0;i<n;i++){
int index = s.charAt(i);
left = Math.max(left,last[index]+1);
res = Math.max(res,i-left+1);
last[index] = i;
}
return res;
}
}
- 中等 盛最多水的容器 Container with Most Water
20.07.06
思路:双指针,向中间收
class Solution {
int res = 0;
public int maxArea(int[] height) {
int left = 0;
int right = height.length-1;
while(left<right){
res = Math.max(res,(right-left)*Math.min(height[left],height[right]));
if(height[left]<height[right]) left++;
else right--;
}
return res;
}
}
- 中等 三数之和 3 Sum
20.07.06
思路:双指针
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ls = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) { // 跳过可能重复的答案
int l = i + 1, r = nums.length - 1, sum = 0 - nums[i];
while (l < r) {
if (nums[l] + nums[r] == sum) {
ls.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
} else if (nums[l] + nums[r] < sum) {
while (l < r && nums[l] == nums[l + 1]) l++;
l++;
} else {
while (l < r && nums[r] == nums[r - 1]) r--;
r--;
}
}
}
}
return ls;
}
}
- 中等 最接近的三数之和 3 Sum Closest
20.07.06
思路: 没什么思路,写熟了就好。
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closestNum = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length - 2; i++) {
int l = i + 1, r = nums.length - 1;
while (l < r){
int threeSum = nums[l] + nums[r] + nums[i];
if (Math.abs(threeSum - target) < Math.abs(closestNum - target)) {
closestNum = threeSum;
}
if (threeSum > target) {
r--;
} else if (threeSum < target) {
l++;
} else {
return target;
}
}
}
return closestNum;
}
}
- 中等 四数之和 4 Sum
20.07.06
思路:和三数之和完全一样,不过要加上去重的部分。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for(int a=0;a<nums.length-3;a++){
if(a>0 && nums[a] == nums[a-1]) continue;
for(int b=a+1;b<nums.length-2;b++){
if(b>a+1 && nums[b] == nums[b-1]) continue;
int c = b+1;
int d = nums.length-1;
while(c<d){
int sum = nums[a]+nums[b]+nums[c]+nums[d];
if(sum == target){
ans.add(Arrays.asList(nums[a],nums[b],nums[c],nums[d]));
while(c<d && nums[c] == nums[c+1]) c++;
while(c<d && nums[d] == nums[d-1]) d--;
c++;d--;
}else if(sum < target){
while(c<d && nums[c] == nums[c+1]) c++;
c++;
}else{
while(c<d && nums[d] == nums[d-1]) d--;
d--;
}
}
}
}
return ans;
}
}
- 中等 删除链表的倒数第N个元素 Remove N-th Node From End of List
20.07.10
思路:这个题做过无数遍,只是我不知道Java的链表怎么写。很舒适的一个题。打键盘非常有节奏感。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = head;
while(n>0){
fast = fast.next;
n--;
}
while(fast!=null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
- 简单 删除排序数组中的重复项 Remove Duplicates From Sorted Array
20.07.10
思路:没什么思路。见下面。坑多。
class Solution {
public int removeDuplicates(int[] nums) {
int j=0;
for(int i=1;i<nums.length;i++){ //i=1是因为第一个总是要保留的
if(nums[i]!=nums[j]){
nums[++j] = nums[i];//++j也是因为第一个要保留,所以先加再换
}
}
return j+1;//注意一下,不然最后一个进不来
}
}
- 简单 移除元素 Remove Element
20.07.10
思路:和26题其实完全一样,甚至比26题更简单。
class Solution {
public int removeElement(int[] nums, int val) {
int j = 0;
for(int i=0;i<nums.length;i++){
if(nums[i]!=val){
nums[j++] = nums[i];
}
}
return j;
}
}
- 简单 实现strStr() Implement strStr
20.07.10
思路:没什么,只是我不知道Java的chatAt怎么用。
class Solution {
public int strStr(String haystack, String needle) {
//各种空值条件处理
if (needle == null || needle.length() ==0 ) {
return 0;
}
if (haystack == null) {
return -1;
}
if (haystack.length() < needle.length()) {
return -1;
}
//遍历
for (int i = 0; i < haystack.length(); i++) {
if (haystack.length() - i < needle.length()) {
return -1;
}
for (int j = 0; j < needle.length(); j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
break;
} else {
if (j == needle.length() - 1) {
return i;
}
}
}
}
return -1;
}
}
- 困难 接雨水 Trapping Rain Water
20.07.10
思路:记录左边和右边的最小值,然后累加。这是在刷Java的时候看到的一个思路。本来我是想像以前一样做两个list的,但是后来我忘了Java的List怎么构造。这实际上是一个上述思路的化简版本,只用一个数组做。有点像11题的做法了。
class Solution {
public int trap(int[] height) {
int min = 0, max = 0;
int l = 0, r = height.length - 1;
int vol = 0;
while(l<r){
min = height[height[l]<height[r]?l++:r--];
max = Math.max(min,max);
vol += max-min;
}
return vol;
}
}
- 中等 旋转链表 Rotate List
20.07.10
思路:不过是一个快慢指针连成环然后解开。我得想想为什么之前的不对。把while改成for为什么就对了呢。
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null || k==0) return head;
ListNode slow = head;
ListNode fast = head;
int n = 1;
while(fast.next!=null){
fast = fast.next;
n++;
}
fast.next = head;
int mov = n - (k%n);
for(int i=0;i<mov;i++){
fast = fast.next;
slow = slow.next;
}
fast.next = null;
return slow;
}
}
- 中等 颜色分类 Sort Colors
20.07.10
思路:三路排序,Java里面没有swap函数,写了半天。注意right不能小于i,这样可能会把2换到中间来。
class Solution {
public void sortColors(int[] nums) {
if(nums.length == 0) return;
int left = 0;
int right = nums.length-1;
int temp;
int i = 0;
while(i<=right){
if(nums[i] == 0){
nums[i++] = nums[left];
nums[left++] = 0;
}else if(nums[i] == 2){
nums[i] = nums[right];
nums[right--] = 2;
}else{
i++;
}
}
return;
}
}
- 中等 删除排序数组中的重复项II Remove Duplicates from Sorted Array II
20.07.10
思路:这题我想起来了,就是那个中间等于前后两个那个题。非常妙。
class Solution {
public int removeDuplicates(int[] nums) {
int n = nums.length;
if(n == 0) return 0;
int index = 0;
for(int i=0;i<n;i++){
if(i>0 && i<n-1 && nums[i] == nums[i-1] && nums[i] == nums[i+1]){
continue;
}
nums[index++] = nums[i];
}
return index;
}
}
- 中等 分隔链表 Partition List
20.07.10
思路:我以为有什么新思路,结果还是两个表。
class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null) return head;
ListNode dummy1 = new ListNode(0);
ListNode dummy2 = new ListNode(0);
ListNode p = head;
ListNode p1 = dummy1;
ListNode p2 = dummy2;
while(p!=null){
if(p.val < x){
dummy1.next = p;
dummy1 = dummy1.next;
}else{
dummy2.next = p;
dummy2 = dummy2.next;
}
p = p.next;
}
dummy1.next = p2.next;
dummy2.next = null;
return p1.next;
}
}
- 简单 合并两个有序数组 Merge Sorted Array
20.07.10
思路:没什么,很熟悉了。边界条件要非常小心。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int right = m+n-1;
int right1 = m-1;
int right2 = n-1;
while(right!=right1){
if(right1>=0 && nums1[right1]>nums2[right2]){
nums1[right--] = nums1[right1--];
}else{
nums1[right--] = nums2[right2--];
}
}
return;
}
}
- 简单 验证回文串 Valid Panlindrome
20.07.11
思路:啊,字符串呜呜呜呜。
class Solution {
public boolean isPalindrome(String s) {
if(s == null) return true;
s = s.toLowerCase();
StringBuilder str = new StringBuilder(1);
for(char c:s.toCharArray()){
if((c >= '0' && c<='9')||(c >= 'a' && c <= 'z')){
str.append(c);
}
}
return str.toString().equals(str.reverse().toString());
}
}
- 简单 环形链表 Linked List Cycle
20.07.11
思路:快慢指针,不过初始化的时候要fast = head.next。
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) return false;
ListNode slow = head;
ListNode fast = head.next;
while(fast != slow){
if(fast.next == null || fast.next.next == null) return false;
fast = fast.next.next;
slow = slow.next;
}
return true;
}
}
- 中等 环形链表II Linked List Cycle II
20.07.11
思路:这题描述不清楚,要返回什么都没讲清,虽然思路很清楚。
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null) return null;
ListNode fast = head, slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow) break;
}
if(fast == null || fast.next == null) return null; //不存在环的情况
fast = head; //可能出现在第一个节点
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
- 简单 两数之和II-输入有序数组 Two Sum II-Input Array is Sorted
20.07.11
思路:做过三数之和的对这个应该不陌生。要记得new int[] 的方法。
class Solution {
public int[] twoSum(int[] numbers, int target) {
if(numbers == null) return null;
int left = 0;
int right = numbers.length-1;
while(left<right){
int sum = numbers[left] + numbers[right];
if(sum < target){
left++;
}else if(sum > target){
right--;
}else{
return new int[]{left+1,right+1};
}
}
return null;
}
}
- 中等 长度最小的子数组 Minimum Size Subarray Sum
20.07.11
思路:一个滑动窗口。我觉得算简单题。
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int i = 0;
int len = 0;
int sum = 0;
for(int j=0;j<nums.length;j++){
sum += nums[j];
while(sum >= s){
len = len == 0 ? j-i+1 : Math.min(len,j-i+1);
sum -= nums[i++];
}
}
return len;
}
}
- 中等 回文链表 Panlindrome Linked List
20.07.11
思路:分为两个部分。第一个是找中点,非常简单。第二个是翻转链表,这个不容易。这里使用的递归的方法写的。
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null) return true;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
slow = reverse(slow.next);
while(slow != null){
if(head.val != slow.val){
return false;
}
head = head.next;
slow = slow.next;
}
return true;
}
public ListNode reverse(ListNode head){
if(head.next == null) return head;
ListNode newHead = reverse(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
- 中等 较小的三数之和 3 Sum Smaller
20.07.11
思路:count+=right-left,真是精妙。
class Solution {
public int threeSumSmaller(int[] nums, int target) {
int count = 0;
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
int left = i+1;
int right = nums.length-1;
while(left<right){
int sum = nums[i] + nums[left] + nums[right];
if(sum < target){
count+= right-left;left++;
}else{
right--;
}
}
}
return count;
}
}
- 简单 移动零 Move Zeros
20.07.11
思路:2分钟一次AC。
class Solution {
public void moveZeroes(int[] nums) {
if(nums == null || nums.length == 0) return;
int slow = 0;
for(int i=0;i<nums.length;i++){
if(nums[i] != 0){
nums[slow++]=nums[i];
}
}
while(slow<nums.length){
nums[slow++] = 0;
}
return;
}
}
- 中等 寻找重复数 Find The Duplicate Number
20.07.11
思路:快慢指针。而且循环条件是nums[slow]!=nums[left]。
class Solution {
public int findDuplicate(int[] nums) {
int slow = 0;
int fast = 0;
while(true){
fast = nums[nums[fast]];
slow = nums[slow];
if(slow == fast){
fast = 0;
while(nums[slow] != nums[fast]){
slow = nums[slow];
fast = nums[fast];
}
return nums[slow];
}
}
}
}