代码随想录
数组
二分查找
class Solution {
public int search(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]<target){
left=mid+1;
}
else if(nums[mid]>target){
right=mid-1;
}
else{
return mid;
}
}
return -1;
}
}
移除元素
class Solution {
public int removeElement(int[] nums, int val) {
int left=0;
int right=nums.length-1;
while(left<=right){
if(nums[left]==val){
nums[left]=nums[right];
right--;
}
else{
left++;
}
}
return right+1;
}
}
有序数组的平方
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int minp = 0;
for(int i=0;i<n;i++){
if(Math.abs(nums[i])<Math.abs(nums[minp])){
minp=i;
}
}
int[] res = new int[n];
res[0]=nums[minp]*nums[minp];
int p=1;
int left=minp-1;
int right=minp+1;
while(p<n){
if(left>=0 && right<n){
if(Math.abs(nums[left])<Math.abs(nums[right])){
res[p++]=nums[left]*nums[left];
left--;
}else{
res[p++]=nums[right]*nums[right];
right++;
}
}else{
break;
}
}
if(left>=0){
while(left>=0){
res[p++]=nums[left]*nums[left];
left--;
}
}
if(right<n){
while(right<n){
res[p++]=nums[right]*nums[right];
right++;
}
}
return res;
}
}
长度最小的子数组 ★
思想:滑动窗口
right用来指示窗口的右边界,当right向右移动直到满足题目条件时,收缩窗口的左边界。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int sum = 0;
int left = 0;
for(int right=0;right<nums.length;right++){
sum+=nums[right];
while(sum>=target){
result = Math.min(result, right-left+1);
sum -= nums[left++];
}
}
return result==Integer.MAX_VALUE ? 0 : result;
}
}
水果成篮(滑动窗口)
class Solution {
public int totalFruit(int[] fruits) {
HashMap<Integer, Integer> tree = new HashMap<>();
int left=0;
int result=0;
int sum=0;
for(int right=0;right<fruits.length;right++){
if(!tree.containsKey(fruits[right])){
tree.put(fruits[right], 1);
sum++;
}else{
tree.replace(fruits[right], tree.get(fruits[right])+1);
sum++;
}
while(tree.size()>2){
if(tree.get(fruits[left])>1){
tree.put(fruits[left], tree.get(fruits[left])-1);
left++;
sum--;
}
else{
tree.remove(fruits[left]);
left++;
sum--;
}
}
result = Math.max(result, sum);
}
return result;
}
}
螺旋矩阵(模拟)
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int count=0;
int upbound=0;
int downbound=n-1;
int leftbound=0;
int rightbound=n-1;
int num=1;
while(true){
if(num>(n*n))break;
//left to right
for(int i=leftbound;i<=rightbound;i++){
matrix[upbound][i]=num++;
if(num>(n*n))break;
}
upbound++;
//up to down
for(int i=upbound;i<=downbound;i++){
matrix[i][rightbound]=num++;
if(num>(n*n))break;
}
rightbound--;
//right to left
for(int i=rightbound;i>=leftbound;i--){
matrix[downbound][i]=num++;
if(num>(n*n))break;
}
downbound--;
//down to up
for(int i=downbound;i>=upbound;i--){
matrix[i][leftbound]=num++;
if(num>(n*n))break;
}
leftbound++;
}
return matrix;
}
}
链表
移除链表元素
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode newhead = new ListNode(0);
newhead.next = head;
ListNode fast = head;
ListNode slow = newhead;
while(fast!=null){
if(fast.val == val){
slow.next=fast.next;
fast=slow.next;
}
else{
fast=fast.next;
slow=slow.next;
}
}
return newhead.next;
}
}
设计链表
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size=0;
head = new ListNode(0);
}
public int get(int index) {
if(index<0 || index>=size){
return -1;
}
ListNode p = head;
for(int i=0;i<=index;i++){
p=p.next;
}
return p.val;
}
public void addAtHead(int val) {
ListNode temp = new ListNode(val);
// temp.next=head;
// head=temp;
temp.next=head.next;
head.next=temp;
size++;
}
public void addAtTail(int val) {
ListNode p = head;
while(p.next!=null){
p=p.next;
}
ListNode temp = new ListNode(val);
p.next = temp;
size++;
}
public void addAtIndex(int index, int val) {
if(index>=0 && index<=size){
ListNode temp = head;
ListNode newnode = new ListNode(val);
for(int i=0;i<index;i++){
temp=temp.next;
}
newnode.next = temp.next;
temp.next=newnode;
size++;
}
}
public void deleteAtIndex(int index) {
if(index>=0 && index<size){
ListNode p = head;
for(int i=0;i<index;i++){
p=p.next;
}
p.next=p.next.next;
size--;
}
}
}
class ListNode{
int val;
ListNode next;
public ListNode(int val){
this.val = val;
}
}
反转链表(To do 其他解法)
迭代解法:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null)
return null;
ListNode newHead = new ListNode(0);
ListNode p = head;
ListNode q = head;
while(p!=null){
q=p.next;
p.next=newHead.next;
newHead.next=p;
p=q;
}
return newHead.next;
}
}
两两交换链表中的节点
pre:需要交换的两节点的上一个节点
slow:交换双方中后一个节点
fast:交换双方中前一个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null)
return null;
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode pre = newHead;
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null){
pre.next = fast;
slow.next = fast.next;
fast.next = slow;
pre = slow;
slow = slow.next;
if(slow==null)
break;
fast = slow.next;
}
return newHead.next;
}
}
删除链表的倒数第N个结点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)
return null;
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode fast = head;
ListNode slow = newHead;
for(int i=0;i<n;i++){
fast=fast.next;
}
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return newHead.next;
}
}
链表相交
思路:遍历两个链表得到链表长度,计算差值,让长的先走
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null || headB==null)
return null;
ListNode p1 = headA;
ListNode p2 = headB;
int len1 = 0;
int len2 = 0;
int sub = 0;
while(p1!=null){
len1++;
p1=p1.next;
}
while(p2!=null){
len2++;
p2=p2.next;
}
if(len1>len2){
sub = len1 - len2;
p1 = headA;
p2 = headB;
for(int i=0;i<sub;i++){
p1=p1.next;
}
while(p1!=null && p2!=null){
if(p1==p2)
break;
p1 = p1.next;
p2 = p2.next;
}
}else{
sub = len2 - len1;
p2 = headB;
p1 = headA;
for(int i=0;i<sub;i++){
p2 = p2.next;
}
while(p1!=null && p2!=null){
if(p1==p2)
break;
p1 = p1.next;
p2 = p2.next;
}
}
if(p1==p2)
return p1;
else
return null;
}
}
环形链表Ⅱ
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null || head.next==null)
return null;
ListNode fast = head;
ListNode slow = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast==slow)
break;
}
if(fast!=slow)
return null;
slow = head;
while(fast!=slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
哈希表
有效的字母异位词
个人解法:定义一个哈希表,存储一个字符串的字符数量,判断另一个字符串的字符数量情况。比较慢。
class Solution {
public boolean isAnagram(String s, String t) {
HashMap<Character, Integer> word = new HashMap<>();
for(int i=0;i<s.length();i++){
if(word.containsKey(s.charAt(i))){
word.put(s.charAt(i),word.get(s.charAt(i))+1);
}
else{
word.put(s.charAt(i), 1);
}
}
for(int i=0;i<t.length();i++){
if(word.containsKey(t.charAt(i))){
word.put(t.charAt(i), word.get(t.charAt(i))-1);
}
else{
return false;
}
}
for(Integer value : word.values()){
if(value!=0)
return false;
}
return true;
}
}
排序的方法:将两个字符串转换成字符数组并排序,更快。
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
char[] str1 = s.toCharArray();
char[] str2 = t.toCharArray();
Arrays.sort(str1);
Arrays.sort(str2);
return Arrays.equals(str1, str2);
}
}
两个数组的交集
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> res = new HashSet<>();
HashSet<Integer> nums = new HashSet<>();
for(int i=0;i<nums1.length;i++){
nums.add(nums1[i]);
}
for(int i=0;i<nums2.length;i++){
if(nums.contains(nums2[i])){
res.add(nums2[i]);
}
}
int[] result = new int[res.size()];
int i=0;
for(int value : res){
result[i++]=value;
}
return result;
}
}
快乐数
个人解法:
class Solution {
public boolean isHappy(int n) {
String num = String.valueOf(n);
HashSet<Integer> set = new HashSet<>();
int sum = 0;
while(sum!=1){
for(int i=0;i<num.length();i++){
int temp = num.charAt(i)-'0';
sum+=temp*temp;
}
if(set.contains(sum)){
break;
}else{
set.add(sum);
num = String.valueOf(sum);
sum = 0;
}
}
if(sum==1)
return true;
return false;
}
}
简洁:
class Solution {
private int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
Set<Integer> seen = new HashSet<>();
while (n != 1 && !seen.contains(n)) {
seen.add(n);
n = getNext(n);
}
return n == 1;
}
}
两数之和
个人垃圾解法:克隆一个数组进行排序,然后用双指针
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] tmp = new int[nums.length];
for(int i=0;i<nums.length;i++){
tmp[i]=nums[i];
}
Arrays.sort(tmp);
int left=0;
int right=nums.length-1;
while(left<right){
if(tmp[left]+tmp[right]<target){
left++;
}
else if(tmp[left]+tmp[right]>target){
right--;
}
else{
break;
}
}
int[] res = new int[2];
for(int i=0;i<nums.length;i++){
if(nums[i]==tmp[left]){
res[0]=i;
}
}
for(int i=0;i<nums.length;i++){
if(nums[i]==tmp[right] && i!=res[0]){
res[1]=i;
}
}
return res;
}
}
推荐做法:使用哈希表
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
int[] res = new int[2];
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
res[0]=i;
res[1]=map.get(target-nums[i]);
break;
}
else{
map.put(nums[i], i);
}
}
return res;
}
}
四数相加II★
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer, Integer> map = new HashMap<>();
int count = 0;
for(int i=0;i<nums1.length;i++){
for(int j=0;j<nums1.length;j++){
int tmp = nums1[i]+nums2[j];
if(map.containsKey(tmp)){
map.put(tmp, map.get(tmp)+1);
}
else{
map.put(tmp, 1);
}
}
}
for(int i=0;i<nums3.length;i++){
for(int j=0;j<nums4.length;j++){
int tmp = nums3[i]+nums4[j];
tmp = -tmp;
if(map.containsKey(tmp)){
count+=map.get(tmp);
// map.put(tmp, map.get(tmp)-1);
}
}
}
return count;
}
}
赎金信
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
HashMap<Character, Integer> map = new HashMap<>();
for(int i=0;i<magazine.length();i++){
if(!map.containsKey(magazine.charAt(i))){
map.put(magazine.charAt(i), 1);
}
else{
map.put(magazine.charAt(i), map.get(magazine.charAt(i))+1);
}
}
for(int i=0;i<ransomNote.length();i++){
char ch = ransomNote.charAt(i);
if(map.containsKey(ch) && map.get(ch)>0){
map.put(ch, map.get(ch)-1);
}
else{
return false;
}
}
return true;
}
}
三数之和 ★
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> list = new ArrayList<>();
int left=1;
int right=nums.length-1;
for(int i=0;i<nums.length-2;i++){
if(i>0 && nums[i-1]==nums[i])
continue;
left = i+1;
right = nums.length-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]>0){
right--;
}
else if(nums[i]+nums[left]+nums[right]<0){
left++;
}
else{
// List<Integer> tmp = new ArrayList<>();
// tmp.add(nums[i]);
// tmp.add(nums[left]);
// tmp.add(nums[right]);
// list.add(tmp);
list.add(Arrays.asList(nums[i], nums[left], nums[right]));
while(left<right && nums[right]==nums[right-1])right--;
while(left<right && nums[left]==nums[left+1])left++;
left++;
right--;
}
}
}
return list;
}
}
四数之和 ★
解法:双指针
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int left, right;
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
for(int i=0;i<nums.length-3;i++){
if(i>0 && nums[i]==nums[i-1])
continue;
for(int j=i+1;j<nums.length-2;j++){
if(j>i+1 && nums[j]==nums[j-1])
continue;
left=j+1;
right=nums.length-1;
while(left<right){
long tmp = (long)nums[left]+nums[right]+nums[i]+nums[j];
if(tmp>target){
right--;
}
else if(tmp<target){
left++;
}
else if(tmp==target){
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while(left<right && nums[left]==nums[left+1])left++;
while(left<right && nums[right]==nums[right-1])right--;
left++;
right--;
}
}
}
}
return result;
}
}
字符串
反转字符串
class Solution {
public void reverseString(char[] s) {
int left=0;
int right=s.length-1;
while(left<right){
char temp = s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}
}
}
反转字符串II
class Solution {
public String reverseStr(String s, int k) {
char[] str = s.toCharArray();
int index=0;
while(index<str.length){
if(index+2*k<=str.length){
exchangeStr(str, index, index+k-1);
index=index+2*k;
}
else if(index+2*k>str.length && index+k<str.length){
exchangeStr(str, index, index+k-1);
break;
}
else{
exchangeStr(str, index, str.length-1);
break;
}
}
return String.valueOf(str);
}
public void exchangeStr(char[] str, int left, int right){
while(left<right){
char tmp = str[left];
str[left]=str[right];
str[right]=tmp;
left++;
right--;
}
}
}
反转字符串中的单词
class Solution {
public String reverseWords(String s) {
List<String> word = new ArrayList<>();
int p=0;
StringBuilder tmp = new StringBuilder();
while(p<s.length()){
if(s.charAt(p)!=' '){
tmp.append(s.charAt(p));
p++;
}
else {
if(tmp.length()>0){
word.add(tmp.toString());
tmp = new StringBuilder();
}
p++;
}
}
if(tmp.length()>0){
word.add(tmp.toString());
}
StringBuilder result = new StringBuilder();
for(int i=word.size()-1;i>0;i--){
String temp = word.get(i);
result.append(temp);
result.append(" ");
}
result.append(word.get(0));
return result.toString();
}
}