# summary

When looking for the middle node of the chain table, use the fast and slow pointers, when both the fast and slow pointers are initially pointing to the head, the end condition cannot be

```while(fast!=null&&fast.next!=null)
```

Because of this, if I judge that 1, 2, 3, 1, 3, [3, 4] finds 4, my solution is to initially point the fast pointer at the next node of the head node

```ListNode fast=head.next;
```

If the value of hashMap is a List, how to assign all values to List<List>

```new ArrayList<List<String>>(map.values());
```

When simulating a stack with an array, remember to set the top of the stack to -1;

list inversion, Collections.reverse();

Get Queue Header Element of Queue

```queue.peek()/queue.element()
```

java array to list

``` int temp1[]=queue.poll();
List<Integer> list1 = Arrays.asList(temp1[0],temp1[1]);
```

# 2021.08.06 Day 1 Integer

## 1 Swordfinger Offer II 001.Integer Division

Given two integers a and b, the quotient a/b for dividing them requires that the multiplication sign'*', the division sign'/'and the remainder sign'%' not be used.

```class Solution {
public int divide(int a, int b) {
if(a==0x80000000&&b==-1)//Overflow, -2^31/-1
return 0x7FFFFFFF;
int positive=2;//Number of positive numbers marked
if(a>0){
positive--;
a=-a;
}
if(b>0){
positive--;
b=-b;
}
int result=0;
//Divide two negative numbers
while(a<=b){
a=a-b;
result++;
}
return positive==1?-result:result;
}
}
```

optimization

Problem Analysis: When the dividend is large but the dividend is small, the subtraction operation will be performed many times. For example, 2^31/1 performs 2^31 subtractions.
When the dividend is greater than the divisor, continue comparing to determine if the dividend is greater than twice the divisor. If so, continue to determine if the dividend is greater than four, eight, 16 times the dividend,... If the dividend is at most two times the dividend, then the dividend will be subtracted by two times the dividend, and then repeat the remaining dividends in the previous steps.
In order to find 15/2 quotients, first subtract 8 (2^3) from 15 to get 7; Subtract 4 (2^2) from 7 to get 3; Then subtract 2 (2^1) from 3 to get 1, where 1 is less than 2, so the quotient is 3+2+1=7

```class Solution {
public int divide(int dividend, int divisor) {
//-2^31/ -1 = 2^31 overflow
if(dividend == 0x80000000 && divisor == -1){
return 0x7FFFFFFF;
}

int negative = 2;//Used to record positive numbers
//Since negative numbers go beyond the bounds of -2^31 -> 2^31, positive numbers are used to go negative.
if(dividend > 0){
negative --;
dividend = -dividend;
}

if(divisor > 0){
negative --;
divisor = -divisor;
}

//Divide two negative numbers
int result = 0;
while(dividend <= divisor){
int value = divisor;//Statistical subtraction
int quotient = 1;//Statistical quotient
while(value > 0xc0000000 && value + value >= dividend){//Value > 0xc0000000 to prevent value*2 from overflowing
quotient += quotient;//If you can multiply quotient*=2
value += value;//If you can multiply value*=2
}

result += quotient;
dividend -= value;
}
return negative == 1 ? -result : result;

}
}
```

0xc0000000 represents half (-2^31)/2 of the smallest negative integer of 32-bit int type. Since both dividends and dividends have been converted to negative numbers, the form of the above judgment is that dividends are greater than dividends.

Reference resources
Swordfinger Offer II 001.Integer Division

Method 2:
Quick Bit Division

```class Solution {
public int divide(int a, int b) {
int signBit = 0x80000000;
long ans = 0, x = a, y = b;
//Math.abs() is not used directly to avoid divisions or -2^31, where Math.abs() returns with an error
x = x < 0 ? -x : x;
y = y < 0 ? -y : y;
//Example: 60/8=(60-32)/8+4=(60-32-16)/8+2+4=(60-32-16-8)/8+1+2+4=1+2+4=7
while (x >= y) {
long cnt = 1, base = y;
while (x > (base << 1)) {
cnt <<= 1;
base <<= 1;
}
ans += cnt;
x -= base;
}
ans = (((a ^ b) & signBit) == 0) ? ans : -ans;
return (int) ((Integer.MAX_VALUE < ans || ans < Integer.MIN_VALUE) ? Integer.MAX_VALUE : ans);
}
}
```

## 2 Swordfinger Offer II 002.Binary Addition

Given two 01 strings a and b, calculate their sum and output as binary strings.
The input is a non-empty string and contains only the numbers 1 and 0.

```class Solution {
public String addBinary(String a, String b) {
int len1=a.length();
int len2=b.length();
//If the length of the string is different, precede the shorter string with 0
if(len1>len2){
for(int i=0;i<len1-len2;i++)
{
b="0"+b;
}
}
if(len1<len2)
{
for(int i=0;i<len2-len1;i++)
{
a="0"+a;
}
}
len1=a.length();
len2=b.length();
int len3=len1+1;
int arr[]=new int[len3];//The result of the addition may be one more place than the original string
int carry=0;
len3=len3-1;
len1=len1-1;
len2=len2-1;
while(len1>=0&&len2>=0){
if( a.charAt(len1)=='1'&&b.charAt(len2)=='1')
{
if(carry==1)//Carry-1 scenario
arr[len3]=1;
else
arr[len3]=0;
carry=1;//After calculation, the carry is 1
}
else if(a.charAt(len1)=='0'&&b.charAt(len2)=='0')
{
arr[len3]=carry;
carry=0;//After calculation, carry is 0
}
else{
if(carry==1)
arr[len3]=0;
else
arr[len3]=1;
//Carry position does not change after calculation
}
len1--;
len2--;
len3--;
}
arr[0]=carry;//Add rounding to the first element of arr
String str="";
if(arr[0]==1)  str="1";
for(int i=1;i<arr.length;i++)//Split String
str+=arr[i];
return str;

}
}
```

Solution 2: The reason is the same, but very simple
Reference resources: Binary Sum

```class Solution {
public String addBinary(String a, String b) {
StringBuffer ans = new StringBuffer();

int n = Math.max(a.length(), b.length()), carry = 0;
for (int i = 0; i < n; ++i) {
carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
ans.append((char) (carry % 2 + '0'));
carry /= 2;
}

if (carry > 0) {
ans.append('1');
}
ans.reverse();

return ans.toString();
}
}
```

## 3 Swordfinger Offer II 003.Number of 1 of the first n digit binaries

```class Solution {
public int[] countBits(int n) {
int[] res = new int[n+1];
for(int i=1;i<n+1;i++)
res[i] = res[i>>1] + (i%2);
return res;
}
}
```

```class Solution {
public int[] countBits(int n) {
int[] bits = new int[n + 1];
for (int i = 1; i <= n; i++) {
bits[i] = bits[i & (i - 1)] + 1;
}
return bits;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

```class Solution {
public int[] countBits(int n) {
int[] bits = new int[n + 1];
for (int i = 0; i <= n; i++) {
bits[i] = countOnes(i);
}
return bits;
}

public int countOnes(int x) {
int ones = 0;
while (x > 0) {
x &= (x - 1);
ones++;
}
return ones;
}
}
```

# 2021.08.07 Day 2 Integer

## 4 Swordfinger Offer II 004. Numbers that occur only once

Give you an array of integers, nums, where each element occurs exactly three times except once. Find out and return the element that occurs only once.

Idea 1: Hash tables, map elements and the number of occurrences of that element, and finally traverse

Idea 2: Bit operation

If one number occurs once and the other books occur twice, then we can do exclusive or operations on the elements of the entire array, and the result is a number that occurs only once

Now that the other numbers appear three times, we can consider adding up each binary bit of all the numbers separately
Because three duplicate numbers, their binary bits are the same, add up to either 0 or 3. If you don't duplicate the binary bits of that number, they may become 0 or 4. We take a module of 3 and the binary bits of the duplicate number.

How do I get the nth binary bit of each number?

Consider moving this number one bit to the right and then one bit with it (for example, 1011, take the second binary bit, note that the rightmost is the first binary bit, 1011 shifts one bit to the right to 0101,0101&0001=1, and this binary bit is taken out

So, take out the formula for the nth binary bit of a number
x>>(n-1)&1

What do I do when I get the modeled value?
Initialize the result to 0, for example, if the first binary bit is 1, then you only need to add or add the result to the value of the left shift of 0 bits, which means to keep all binary 1's as

If the third binary bit is 1, then you only need to phase the result with the value (0100) moved 2 bits to the left.

```class Solution {
public int singleNumber(int[] nums) {
int result=0;
for(int i=0;i<32;i++) {
int temp=0;
for(int j=0;j<nums.length;j++)
{
temp+=(nums[j]>>i)&1;
}
if(temp%3!=0)
result|=(1<<i);
}
return result;
}
}
```

## 5 Swordfinger Offer II 005. Maximum product of word length

Given a string array words, calculate the maximum product of the length of words[i] and words[j] when they do not contain the same character. Assume that the string contains only lowercase letters in English. If there is no pair of strings that do not contain the same character, return 0.

Idea 1: Violent enumeration (which will time out), for each string, enumerate its combination with the string after it to see if there are duplicate characters, or calculate the length product of both

```class Solution {
public int maxProduct(String[] words) {
int max=0;
for(int i=0;i<words.length;i++){
for(int j=i;j<words.length;j++){
if(!isSame(words[i],words[j])){
max=Math.max(max,words[i].length()*words[j].length());
}
}
}
return max;
}
public boolean  isSame(String a,String b){
for(int i=0;i<a.length();i++){
for(int j=0;j<b.length();j++){
if(a.charAt(i)==b.charAt(j))
return true;
}
}
return false;
}
}
```

Idea 2: Bit operation
Consider how to reduce the complexity of comparing two strings to see if they have the same character. You can convert a string to an integer, such as
When a appears, the conversion to an integer is result|=1< 0
Appear z, result |=1< 25
Comparing two strings to see if they have the same character can be converted to comparing whether the corresponding integer of the two strings is 0 and 0, indicating that the characters contained in the two strings are not duplicated (in binary bit, the number in binary bit 1 is just wrong).

Reference resources: Clever use of the first 26 bits of integers to store 26 letters

```public static int maxProduct2(String[] words) {
int length = words.length;
int[] ints = new int[length];
for (int i = 0; i < length ; i++) {
for (char c : words[i].toCharArray()){
ints[i] |= (1 << (c - 97));//Use integers to represent a string in word
}
}
int re = 0;
for (int i = 0; i < length -1 ; i++) {//Compare integers and get the maximum length
int pre1 = ints[i];
for (int j = i + 1; j < length; j++) {
int pre2 = ints[j];
if ((pre1 & pre2) == 0){//And operation
int te = words[i].length() * words[j].length();
re = re >= te ? re : te;
}

}
}
return re;
}

Author: closes
Source: Force buckle ( LeetCode)
```

## 6 Swordfinger Offer II 006. Sum of two numbers in a sorted array

Solution ideas: double pointer to end
Head + tail > target shows how much the additive number is, move j forward

```class Solution {
public int[] twoSum(int[] numbers, int target) {
int i=0;int j=numbers.length-1;
while(i<j){
if(numbers[i]+numbers[j]<target)
i++;
else if (numbers[i]+numbers[j]>target)
j--;
else
return new int[]{i,j};
}
return null;
}
}
```

Idea 2: Binary search

Find two numbers in the array so that their sum is equal to the target value. First fix the first number, then look for the second number, which is equal to the target value minus the difference of the first number. Using the ordered nature of arrays, the second number can be found by means of binary search. To avoid repetitive searches, only search to the right of the first number when searching for the second number.

```class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; ++i) {
int low = i + 1, high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] == target - numbers[i]) {
return new int[]{i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return new int[]{-1, -1};
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

# 2021.08.08 Day 3 Array

## 7 Swordfinger Offer II 007.Three Numbers with a Neutral of 0 in the Array

Given a n array of nums containing n integers, determine if there are three elements a, b, c in nums such that a + b + c = 0? Find all ternaries that sum to 0 and are not duplicated.

Think: Note that you want to find non-repeating tuples. If you traverse with violence, you will inevitably find duplicate tuples.
So let's consider sorting the arrays first
First, position a number one at a time in the outer loop. The inner loop is twoSum equivalent to a sorted array. Use double pointers. To avoid duplication, the outer loop should skip the same elements each time.

Overall, the first plus is fixed, the second plus is fixed, and the third plus is solved with a double pointer.

```class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result=new ArrayList();
for(int i=0;i<nums.length;i++) {
if(i>0&&nums[i]==nums[i-1])
continue;  //Skip the same number
int k=nums.length-1;
for(int m=i+1;m<nums.length;m++){
if(m>i+1&&nums[m]==nums[m-1])
continue;    //Skip the same number
while(m<k){
if(nums[m]+nums[k]>0-nums[i])
else if(nums[m]+nums[k]<0-nums[i])
break;   //Because we have fixed the left pointer, the left pointer cannot move, adding up smaller cases is not satisfactory, break directly
else{
List<Integer>list=new ArrayList();//Notice where the list was created
break;
}
}
}
}
return result;
}
}
```

The official solution will be faster

```class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
// Enumeration a
for (int first = 0; first < n; ++first) {
// Requires a different number from the last enumeration
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// The pointer corresponding to c initially points to the rightmost end of the array
int third = n - 1;
int target = -nums[first];
// Enumeration b
for (int second = first + 1; second < n; ++second) {
// Requires a different number from the last enumeration
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// You need to make sure that the pointer for b is on the left side of the pointer for c
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// If pointers coincide, increase with b
// There will be no C that satisfies a+b+c=0 and b<c, so you can exit the loop
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
List<Integer> list = new ArrayList<Integer>();
}
}
}
return ans;
}
}
```

```class Solution {
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList();
int len = nums.length;
if(nums == null || len < 3) return ans;
Arrays.sort(nums); // sort
for (int i = 0; i < len ; i++) {
if(nums[i] > 0) break; // If the current number is greater than 0, the sum of the three must be greater than 0, so end the cycle
if(i > 0 && nums[i] == nums[i-1]) continue; // Duplicate removal
int L = i+1;
int R = len-1;
while(L < R){
int sum = nums[i] + nums[L] + nums[R];
if(sum == 0){
while (L<R && nums[L] == nums[L+1]) L++; // Duplicate removal
while (L<R && nums[R] == nums[R-1]) R--; // Duplicate removal
L++;
R--;
}
else if (sum < 0) L++;
else if (sum > 0) R--;
}
}
return ans;
}
}
```

L++ and R after weight removal - because L and R point to the same number as the previous one at this time

It's really amazing. Please close my knee

## 8 Swordfinger Offer II 008. and shortest subarray greater than or equal to target

Given an array of n positive integers and a target of positive integers.

Find the contiguous subarray [numsl, numsl+1,..., numsr-1, numsr] in the array that satisfies its minimum length and is greater than or equal to the target and return its length. Returns 0 if no qualifying subarray exists.

Idea 1: After the obtained and satisfied conditions >= target, record the current length, then move the left pointer to the right to see if it is still satisfied, until it is not, and then move the right pointer back

```class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int min = nums.length + 1;
int sum = nums[left];
if (sum > target) return 1;
for (int i = 1; i <= nums.length - 1; i++) {
sum += nums[i];
while (sum >= target) {
min = Math.min(min, i - left + 1);
sum = sum - nums[left];
left++;
}
}
return min>nums.length?0:min;
}
}
```
```class Solution {
public int minSubArrayLen(int s, int[] nums) {
int lo = 0, hi = 0, sum = 0, min = Integer.MAX_VALUE;
while (hi < nums.length) {
sum += nums[hi++];
while (sum >= s) {
min = Math.min(min, hi - lo);
sum -= nums[lo++];
}
}
return min == Integer.MAX_VALUE ? 0 : min;
}
}
```

Idea 2: Resolving Violence

```class Solution {
public int minSubArrayLen(int s, int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int ans = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= s) {
ans = Math.min(ans, j - i + 1);
break;
}
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

## 9 Swordfinger Offer II 009. Subarrays whose product is less than K

Given a positive integer array nums and an integer k, find the number of consecutive subarrays within the array whose product is less than k.

Train of thought: Traverse the cumulative product from left to right, if the product is less than k, continue to multiply, if it is greater than k, set the result to 1, move the left pointer one bit backward, and multiply from the left pointer

For example, input: nums = [10,5,2,6], k = 100, which in turn traverses 10, 10*5, 10*5*2, 5*2, 5*2, 5*2*6
8 of 2, 2 * 6, 6

```class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int lo=1;int hi=0; int n=nums.length;int product=1;
int result=0;
while(hi<n){
product*=nums[hi++];
if(product<k){
result++;
if(hi==n){//hi has reached the end and needs to be handled, otherwise the loop condition is not satisfied and the loop ends
product=1;
hi=lo++;
}
}
else{
product=1;
hi=lo++;
}
}
return result;
}
}
```

Idea 2: Consider the number of subarrays that end with each array element and add them together

```class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
if (k <= 1) return 0;
int prod = 1, ans = 0, left = 0;
for (int right = 0; right < nums.length; right++) {
prod *= nums[right];
while (prod >= k) prod /= nums[left++];
ans += right - left + 1;
}
return ans;
}
}
```

# 2021.08.09 Array of Day 4

## 10 Swordfinger Offer II 010.and a subarray of k

Given an array of integers and an integer k, find the number of consecutive subarrays that sum to K in the array.

Think: I want to use a sliding window, but there's too much detail and I've written a lot of scrap code

Look at others
1 Violence

```public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0;
for (int start = 0; start < nums.length; start++) {
int sum = 0;
for (int end = start; end >= 0; end--) {
sum += nums[end];
if (sum == k) {
count++;
}
}
}
return count;
}
}
```

2 Prefix and + hash table optimization

```public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0, pre = 0;
HashMap < Integer, Integer > mp = new HashMap < > ();
mp.put(0, 1);
for (int i = 0; i < nums.length; i++) {
pre += nums[i];
if (mp.containsKey(pre - k)) {
count += mp.get(pre - k);
}
mp.put(pre, mp.getOrDefault(pre, 0) + 1);
}
return count;
}
}
```

## 11 Swordfinger Offer II 011.0 and 1 subarray of the same number

Given a binary array nums, find the longest continuous subarray with the same number of 0 and 1 and return the length of the subarray.

Prefix and Ah Ah Ah

# 2021.08.10 Day 5 Array

## 14 Swordfinger Offer II 014. Variants in strings

Solution ideas: Slide window, store the number of occurrences of characters in the sliding window with two arrays, and compare if two arrays are equal each time you slide

```class Solution {
public boolean checkInclusion(String s1, String s2) {
if(s1.length()>s2.length())
return false;
int nums1[]=new int [26];
int nums2[]=new int[26];
for(int i=0;i<s1.length();i++)
nums1[s1.charAt(i)-'a']+=1;

int left=0;
int right=s1.length()+left-1;
for(int i=0;i<=right;i++)
nums2[s2.charAt(i)-'a']+=1;
if(isEqual(nums1,nums2))
return true;
while(right<s2.length()){
nums2[s2.charAt(left++)-'a']--;
right++;
if(right==s2.length())
return false;
nums2[s2.charAt(right)-'a']++;
if(isEqual(nums1,nums2))
return true;
}
return false;
}
public boolean isEqual(int nums1[],int nums2[]){
for(int i=0;i<nums1.length;i++){
if(nums1[i]!=nums2[i])
return false;
}
return true;
}
}
```

## 15 Swordfinger Offer II 015. All Variants in String

Given two strings s and p, find the substrings of the modifiers for all P in s and return the starting index of those substrings. Do not consider the order in which answers are output.

Variants refer to strings with the same letters but arranged differently.

The idea is to change the code of Question 14 and add the left index to the list where it meets the criteria

```class Solution {
List<Integer>list=new ArrayList();
public List<Integer> findAnagrams(String s, String p) {
return  find(p,s);
}
public List<Integer> find(String s1,String s2){

if(s1.length()>s2.length())
return list;
int nums1[]=new int [26];
int nums2[]=new int[26];
for(int i=0;i<s1.length();i++)
nums1[s1.charAt(i)-'a']+=1;

int left=0;
int right=s1.length()+left-1;
for(int i=0;i<=right;i++)
nums2[s2.charAt(i)-'a']+=1;
if(isEqual(nums1,nums2))
while(right<s2.length()){
nums2[s2.charAt(left++)-'a']--;
right++;
if(right==s2.length())
break;
nums2[s2.charAt(right)-'a']++;
if(isEqual(nums1,nums2))
}
return list;
}
public boolean isEqual(int nums1[],int nums2[]){
for(int i=0;i<nums1.length;i++){
if(nums1[i]!=nums2[i])
return false;
}
return true;
}
}
```

```class Solution {
public List<Integer> findAnagrams(String s, String p) {
int n = s.length(), m = p.length();
List<Integer> res = new ArrayList<>();
if(n < m) return res;
int[] pCnt = new int[26];
int[] sCnt = new int[26];
for(int i = 0; i < m; i++){
pCnt[p.charAt(i) - 'a']++;
sCnt[s.charAt(i) - 'a']++;
}
if(Arrays.equals(sCnt, pCnt)){
}
for(int i = m; i < n; i++){
sCnt[s.charAt(i - m) - 'a']--;
sCnt[s.charAt(i) - 'a']++;
if(Arrays.equals(sCnt, pCnt)){
}
}
return res;
}
}

```

I understand

It is important to note that after a match, the left pointer cannot immediately move after the right pointer, because it may be possible to match the left and right by moving one or two positions at the same time.

```class Solution {
public List<Integer> findAnagrams(String s, String p) {
int n = s.length(), m = p.length();
List<Integer> res = new ArrayList<>();
if(n < m) return res;

int[] pCnt = new int[26];
int[] sCnt = new int[26];

for(int i = 0; i < m; i++){
pCnt[p.charAt(i) - 'a'] ++;
}

int left = 0;
for(int right = 0; right < n; right++){
int curRight = s.charAt(right) - 'a';
sCnt[curRight]++;
while(sCnt[curRight] > pCnt[curRight]){
int curLeft = s.charAt(left) - 'a';
sCnt[curLeft]--;
left++;
}
if(right - left + 1 == m){
}
}
return res;
}
}
```

## 16 Swordfinger Offer II 016. Longest substring without duplicate characters

Given a string s, find out the length of the longest continuous substring that does not contain duplicate characters.

The sliding window method described below is not considered

```class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length()==0)
return 0;
int left=0;
int nums[]=new int[128];
int max=0;
for(int right=0;right<s.length();right++){
int cur=s.charAt(right)-32;
nums[cur]++;
if(nums[cur]>1){//Duplicate character appears
max=Math.max(max,right-left);//Keep the length before the current occurrence of duplicate characters
while(nums[cur]>1){//Move the left pointer back until there are no duplicate characters between left and right
int remove=s.charAt(left)-32;//32 is ASCII for space, that is, all characters have ASCII code after 32
nums[remove]--;//After the left pointer moves, the corresponding character maps to the position in the array minus 1
left++;//Left Pointer Backward
}
}
}
max=Math.max(max,s.length()-left);//This is when the right pointer moves to the end without duplicate characters. Discuss it separately
return max;
}
}
```

For other solutions, refer to: leetcode 3. Longest substring without duplicate characters

# 2021.08.11 Day 6 String

## 18 Swordfinger Offer II 018. Valid palindromes

Given a string s, verify that s is a palindrome string, considering only alphabetic and numeric characters, ignoring case.

In this topic, an empty string is defined as a valid palindrome string.

Solution ideas: double pointer

```class Solution {
public boolean isPalindrome(String s) {
int n = s.length();
int left = 0, right = n - 1;
while (left < right) {
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
++left;
}
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
--right;
}
if (left < right) {
if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
return false;
}
++left;
--right;
}
}
return true;
}
}
```

## 19 Swordfinger Offer II 019. Delete at most one character to get palindrome

Given a non-empty string s, determine whether deleting at most one character from the string will result in a palindrome string.

```class Solution {
int del = 0;  //Record the number of characters deleted
public boolean validPalindrome(String s) {
int i = 0,j = s.length()-1;
while(i < j){
if(s.charAt(i) == s.charAt(j)){
i++;
j--;
}else{
//If not, delete the left or right character before judging. If deleted once, it is not a palindrome string
if(del == 0){
del++;
return validPalindrome(s.substring(i,j)) || validPalindrome(s.substring(i+1,j+1));
}
return false;
}
}
return true;
}
}

```

## 20 Swordfinger Offer II 020. Number of palindrome substrings

Given a string s, calculate how many palindrome substrings are in this string.

Substrings with different starting or ending positions, even if they consist of the same character, are considered different substrings.
thinking

The number of I-centered and (i,i+1) centered outward spreading palindromes is calculated and added.

```class Solution {
public int countSubstrings(String s) {
int result=0;
for(int i=0;i<s.length();i++)
result+=palindrome( s, i)+palindrome(s, i,i+1);
return result;
}
public int palindrome(String s,int i){//i-centric palindrome string
int count=1;//A single character is also a palindrome
int left=i-1;
int right=i+1;
while(left>=0&&right<s.length()&&(s.charAt(left)==s.charAt(right))){
left--;
right++;
count++;
}
return count;
}
public int palindrome(String s,int i,int j){//i,j-centric palindrome string
if(j>=s.length()||s.charAt(i)!=s.charAt(j))
return 0;
int count=1;//It i s also a palindrome when s.charAt(i)=s.charAt(j)
int left=i-1;
int right=j+1;
while(left>=0&&right<s.length()&&(s.charAt(left)==s.charAt(right))) {
left--;
right++;
count++;
}
return count;
}
}
```

Can be simplified with only one central extension function

```class Solution {
public int countSubstrings(String s) {
int result=0;
for(int i=0;i<s.length();i++)
result+=palindrome( s, i,i)+palindrome(s, i,i+1);
return result;
}
public int palindrome(String s,int i,int j){//i,j-centric palindrome string
if(j>=s.length()||s.charAt(i)!=s.charAt(j))
return 0;
int count=1;//It i s also a palindrome when s.charAt(i)=s.charAt(j)
int left=i-1;
int right=j+1;
while(left>=0&&right<s.length()&&(s.charAt(left)==s.charAt(right))) {
left--;
right++;
count++;
}
return count;
}
}
```

Almost, a little more concise

```public class Solution {
public int countSubstrings(String s) {
int ans = 0;
for(int i=0;i<s.length();i++)
ans+=CountSubstringsInternal(s,i,i)+CountSubstringsInternal(s,i,i+1);
return ans;
}
public int CountSubstringsInternal(String s, int l, int r)
{
int cnt=0;
while(l>=0&&r<s.length())
{
if(s.charAt(l--)!=s.charAt(r++)) break;
cnt++;
}
return cnt;
}
}

```

Idea 2: Dynamic planning

Reference resources: Dynamic Planning and Central Diffusion Solutions

```public int countSubstrings(String s) {
int length = s.length();
boolean[] dp = new boolean[length];
int count = 0;//Number of palindrome strings
for (int j = 0; j < length; j++) {
for (int i = 0; i <= j; i++) {
if (s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1])) {
dp[i] = true;
count++;
} else {
dp[i] = false;
}
}
}
return count;
}

Author: sdwwld
Source: Force buckle ( LeetCode)
```

# 2021.08.12 7th Day Chain List

## 21 Swordfinger Offer II 021. Delete the last nth node of the list of chains

Idea 1: Using recursion

```class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
}
return 0;//0th Last Node
if(num==n)
head.next=head.next.next;//Delete the last n nodes, n has said greater than 0, do not consider null pointers here
return 1+num;
}
}
```

Idea 2: Iteration, iteration has been written many times, with the fast pointer, the fast pointer first takes n steps, and then the two pointers walk together. When the fast pointer reaches the end, both pointers take length-n steps, so the board can delete the next node of the node that the slow pointer points to.

```class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
while(n>0){
fast=fast.next;
n--;
}
if(fast==null)//The header node to be deleted
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
}
}
```

You can simplify code by using false header nodes

```class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode(0);
ListNode slow=dummy;
while(n>0){
fast=fast.next;
n--;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}
```

## 22 Swordfinger Offer II 022. Entry node of a ring in a chain table

Given a list of chains, returns the first node where the list of chains begins to ring. The first node that enters the ring along the next pointer from the head node of the chain list is the entry node of the ring. If the list of chains is not looped, null is returned.

Solution ideas: fast slow pointer

```public class Solution {
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(slow==fast){//Fast and slow pointers meet, indicating a ring
while(fast!=slow){//Let the fast pointer point to the head node, and then the fast and slow pointers move at the same time. The point where the fast pointer meets again is the entry point
fast=fast.next;
slow=slow.next;
}
return fast;
}
}
return null;
}
}
```

Idea 2: Hash table, save visited nodes in Set, the first node to be duplicated is the ring entry point

## 23 Swordfinger Offer II 023.First coincident node of two linked lists

Given the header nodes headA and headB of two single-chain tables, find and return the starting node where the two single-chain tables intersect. Returns null if the two linked lists do not intersect.

Idea 1: Double Pointer
The other pointer starts from headB, is empty, and starts from headA
It's the same journey when we meet like this
It is important to note that if there is no intersection between the two lists, the second pass will exit the loop if both pointers point to null

```public class Solution {
while( tempA!=tempB){
}
return tempA;
}
}
```

Idea 2: Hash table
Put a list of chains all into Set, then into the second list of nodes, the first duplicate is the intersection, no duplicate node returns Null

Idea three: Violence two-level while cycle, comparing each node of another list in one chain in turn

# Day 8 list 2021.08.13

## 24 Swordfinger Offer II 024. Reverse Chain List

Idea 1: Iteration

```class Solution {
ListNode pre=null;
ListNode next=null;
while(cur!=null){
next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
}
```

```class Solution {
ListNode dummy=new ListNode(0);
ListNode temp=dummy;
ListNode end=null;
end=temp.next;
}
return dummy.next;
}
}
```

Idea 3: Recursion

```class Solution {
return p;
}
}
```
```public ListNode reverseList(ListNode head) {
// Last node, will become the head node in the end
ListNode last = null;

// Temporarily save next node
// Next node points to previous node
// Execute and record the current node
// Next Node
}

return last;
}

Author: felix-he
Source: Force buckle ( LeetCode)
```

## 25 Swordfinger Offer II 025. Addition of Two Numbers in a Chain List

Given two non-empty linked lists l1 and l2 to represent two non-negative integers. The highest digits are at the beginning of the linked list. Each of their nodes stores only one digit. Adding the two numbers together returns a new linked list.

It can be assumed that neither number starts with zero except the number 0.

Solution ideas: first invert the two list of chains, and then become the second question two numbers added together, then add the inverted list of chains, and then invert the results you get

```class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
l1= reverseList(l1);
l2= reverseList(l2);
return reverseList(node);
}
return p;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2,int a){
if(l1==null&&l2==null)
return a==0?null:new ListNode(a);//The list goes to the end, but there is a carry case
if(l1!=null){
a+=l1.val;
l1=l1.next;
}
if(l2!=null){
a+=l2.val;
l2=l2.next;
}
ListNode node=new ListNode(a%10);
return node;
}
}
```

Idea 2: Using stacks

The main difficulty of this topic is that the order of the digits in the list of chains is opposite to the order in which we add them. In order to process all digits in reverse order, we can use the stack: push all digits into the stack, and then take out the sum one by one. Carry-in situations need to be noted in the calculation.

```class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
while (l1 != null) {
stack1.push(l1.val);
l1 = l1.next;
}
while (l2 != null) {
stack2.push(l2.val);
l2 = l2.next;
}
int carry = 0;
ListNode ans = null;
while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
int a = stack1.isEmpty() ? 0 : stack1.pop();
int b = stack2.isEmpty() ? 0 : stack2.pop();
int cur = a + b + carry;
carry = cur / 10;
cur %= 10;
ListNode curnode = new ListNode(cur);
curnode.next = ans;
ans = curnode;
}
return ans;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

## 26 Swordfinger Offer II 026. Rearrangement list

Ideas: Using stack, putting all the chain list nodes on the stack, and then the next operation is equivalent to taking an element from the stack and inserting it into the chain table on the basis of the original chain table. Four elements need to pop up twice, seven elements need to pop up three times, and the number of popups is divided by the length of the chain table by two

```class Solution {
Stack<ListNode>stack=new Stack();
int count=0;
while(temp!=null){
stack.push(temp);
temp=temp.next;
count++;
}
int mod=count/2;//Stack pops up to this many times
while(mod>0){
ListNode next=temp.next;
temp.next=stack.pop();
temp=temp.next;
temp.next=next;
temp=next;
mod--;
}
temp.next=null;
}
}
```

Can merge again

# 2021.08.14 9th day list

## 27 Swordfinger Offer II 027. Palindrome Chain List

Given the head node of a chain table, determine if it is a palindrome chain table.

If a chain table is palindrome, then the chain list node sequence is the same from going backward to looking backward to looking forward.

Solution Idea 1: Store all the values of the node on the stack, and then start traversing from the beginning to see if each value is equal to the top of the stack

```class Solution {
Stack<Integer>stack=new Stack();
while(temp!=null){
stack.push(temp.val);
temp=temp.next;
}
while(temp!=null){
if(temp.val!=stack.pop())
return false;
temp=temp.next;
}
return true;
}
}
```

Idea 2: Find the intermediate node, reverse the second half of the list, and compare
It is important to note that if the length of the chain table is odd, the first part will be one more length than the second half.
If the length of the chain table is even, the length of the first and second half are equal
So during traversal, if the second half of the traversal is complete, the traversal stops

```class Solution {
//Solution Idea 2, find the intermediate node, reverse the latter half of the list
return true;
ListNode reverse=reverseList(mid.next);//Head Node After Later Half Segment Inversion
while(reverse!=null){
return false;
reverse=reverse.next;
}
return true;
}

return slow;
}
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
return p;
}
}
```

Above is to find the midpoint and then reverse, or to find the midpoint, while traversing, while reversing

```class Solution {
return true;
}
ListNode pre = head, prepre = null;
while(fast != null && fast.next != null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
pre.next = prepre;
prepre = pre;
}
if(fast != null) {
slow = slow.next;
}
while(pre != null && slow != null) {
if(pre.val != slow.val) {
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}
```

Idea 3 Put the element in the array and use the double pointer

```class Solution {
List<Integer> vals = new ArrayList<Integer>();

// Copy the values of the list of chains into the array
while (currentNode != null) {
currentNode = currentNode.next;
}

// Use double pointer to determine palindrome
int front = 0;
int back = vals.size() - 1;
while (front < back) {
if (!vals.get(front).equals(vals.get(back))) {
return false;
}
front++;
back--;
}
return true;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

Idea 4 Recursion

```class Solution {
private ListNode frontPointer;

private boolean recursivelyCheck(ListNode currentNode) {
if (currentNode != null) {
if (!recursivelyCheck(currentNode.next)) {
return false;
}
if (currentNode.val != frontPointer.val) {
return false;
}
frontPointer = frontPointer.next;
}
return true;
}

}
}
```

## 28 Swordfinger Offer II 028. Flattening Multilevel Two-way Chain List

In a multilevel two-way Chain table, in addition to pointers to the next and previous nodes, it also has a sublist pointer, which may point to a separate two-way Chain table. These sublists may also have one or more of their own subitems, and so on, to generate a multilevel data structure, as shown in the following example.

Given the head node at the first level of the list, flatten the list by flattening such a multilevel two-way list into a common two-way list so that all the nodes appear in a single-level double-chain list.

Idea 1 Recursion

```class Solution {
private Node node;
return null;
}
if(node != null) {
node.child = null;
}
//When you start traversing your child (e.g. 3, 7), the next is changed, so save it with nextNode
flatten(nextNode);
}
}
```

iteration

```class Solution {

Deque<Node> stack = new ArrayDeque<>();

while (!stack.isEmpty()) {
curr = stack.pop();
prev.next = curr;
curr.prev = prev;

if (curr.next != null) stack.push(curr.next);
if (curr.child != null) {
stack.push(curr.child);
// don't forget to remove all child pointers.
curr.child = null;
}
prev = curr;
}
// detach the pseudo node from the result
}
}

Author: LeetCode
Source: Force buckle ( LeetCode)
```

## 29 Swordfinger Offer II 029. Sorted Circular Chain List

``` class Solution {
public Node insert(Node head, int insertVal) {
if(head==null)//The original list is empty. Create a new list and form a ring according to the title
{
}
Node cur = head,max=null;//max is used to handle cases where the insertion value is less than the current minimum and greater than the current maximum
{
//Find insertion points that are greater than or equal to the current value and less than or equal to the next value.
if(cur.val<=insertVal&&cur.next.val>=insertVal) break;
//By the way, find the tail in ascending order
if(cur.val>cur.next.val) max=cur;
cur=cur.next;
}
//The ascending end end end is not found after traversing, so it must be the previous Node of the head, which is now cur
if(max==null) max=cur;
//Successfully find an insertion point that is greater than or equal to the current value and less than or equal to the next value, then insert it
if(cur.val<=insertVal&&cur.next.val>=insertVal)
{
var nn = new Node(insertVal,cur.next);
cur.next=nn;
}
//If no insertion point is found, then whether it is greater than the maximum or smaller than the minimum, it is after the current maximum (and certainly before the current minimum)
else
{
var nn = new Node(insertVal,max.next);
max.next=nn;
}
}
}

```

# 2021.08.15 Day 10 Hash Table

## 30 Swordfinger Offer II 030. Insertion, deletion and random access are containers for O(1)

HashMap+ArrayList
To delete O(1) in an array, swap the end data to delete the data, and then delete the end data.

HashMa key stores element values, value stores index of elements

```class RandomizedSet {
// Solution 1
// HashMap + ArrayList
private Random random;
private Map<Integer, Integer> map;
private List<Integer> list;

/** Initialize your data structure here. */
public RandomizedSet() {
random = new Random();
// Position of elements in a list in a map storage set
map = new HashMap<>();
list = new ArrayList<>();
}

/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if (map.containsKey(val)) {
return false;
}
map.put(val, list.size());
return true;
}

/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if (!map.containsKey(val)) {
return false;
}
int size = list.size();
int idx = map.get(val);
// If the element to be removed is not the last item in the list, move the element of the last item to the location to be removed
if (idx < size - 1) {
int lastItem = list.get(size - 1);
list.set(map.get(val), lastItem);
map.put(lastItem, idx);
}
list.remove(size - 1);
map.remove(val);
return true;
}

/** Get a random element from the set. */
public int getRandom() {
return list.get(random.nextInt(list.size()));
}
}

/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet obj = new RandomizedSet();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/

```

The main requirement of this topic is to achieve the complexity that all three operations are o(1). First, the complexity of insertion is o(1). Most data structures can achieve the complexity. The difficulty lies in random access and deletion. It's easy to think of hash tables for the time complexity of deletion, and random access is easy to think of arrays accessed with subscripts.

Reference resources:

```public class RandomizedSet {

private class Node{
Node pre;
Node next;
int val;

public Node(Node pre, Node tail, int val) {
this.pre = pre;
this.next = tail;
this.val = val;
}

public Node() {
}

public Node(int val) {
this.val = val;
}
}

Node tail;
Map<Integer,Node> map;
ArrayList<Node> list;
public RandomizedSet() {
tail=new Node();
map=new HashMap<>();
list=new ArrayList<>();
}

/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if(map.containsKey(val))
return false;
Node node=new Node(val);
tail.pre.next=node;
node.pre=tail.pre;
node.next=tail;
tail.pre=node;
map.put(val,node);
return true;
}

/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if (!map.containsKey(val))
return false;
Node node=map.get(val);
node.pre.next=node.next;
node.next.pre=node.pre;
map.remove(val);
list.remove(node);
return true;
}

/** Get a random element from the set. */
public int getRandom() {
int index=(int)(Math.random()*list.size());
return list.get(index).val;
}

}
```

## 31 Swordfinger Offer II 031. Minimum recently used cache

This is the code I wrote myself
First, the infrastructure is to use HashMap and two-way chaining tables. HashMap inserts and finds elements very quickly, but not orderly. Two-way chaining tables insert and delete quickly and orderly, but locating elements to delete takes time, so combining them

With a two-way chain table and HashMap,HashMap's key stores the incoming key, and the Value store encapsulates the Node type of key and value
We define a function to delete nodes and a function to insert nodes in the chain header

Delete: Depending on the key passed in, go to hashMap to check if there is a corresponding Key. If not, go back to -1 directly. If there is, delete this node from its current location because it is a two-way Chain table, so delete element designs the pointer of the node before and after the current element changes to point to

Insert Head: You can use a false head, which is equivalent to inserting a node after the head node. It is very simple

```class LRUCache {
private int cap;
private int count=0;//Count how many elements are currently stored
private Map<Integer,Node>map=new HashMap();
Node tail=null;//Record the end of a two-way chain table
public LRUCache(int capacity) {
this.cap=capacity;
}
public int get(int key) {
if(map.containsKey(key)){
Node node=map.get(key);
delete(node.key);
return node.val;
}
return -1;
}

public void put(int key, int value) {
Node node=new Node(key,value);
if(map.containsKey(key)){
delete(key);//If there is a current key in the map, remove it first.
}
else {
if(count==cap){
delete(tail.key);
}
else{
}
}
}

public void delete(int key){
Node node=map.get(key);
if(head.next!=null){//There is not only one node
}
else{//When there is only one node
tail=null;
}
}
else if(node==tail){//Is the last node
if(tail.pre!=null)//There is not only one node
tail.pre.next=null;
tail=tail.pre;//Only one node will execute
}
else{
node.pre.next=node.next;
node.next.pre=node.pre;
}
map.remove(key);
count--;
}

else {//Current list has elements
}
count++;
map.put(node.key,node);
}
}
class Node{
int key;
int val;
Node pre;
Node next;
public Node(int key,int val){
this.key=key;
this.val=val;
}
}

/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
```

Seeing a solution is similar to what I think, but simpler than what I see

```class ListNode {
//Member variables
int key;
int value;
ListNode next;
ListNode prev;

//Construction method
public ListNode(int key, int value){
this.key = key;
this.value = value;
}

}

class LRUCache {
//Member variables
private ListNode tail;//Virtual Tail Node
private Map<Integer, ListNode> numToNode;//The key of the hash table is the key of the cache
private int capacity;

public LRUCache(int capacity) {
numToNode = new HashMap<>();

//Initialize Bi-directional Chain List
tail = new ListNode(-1, -1);

this.capacity = capacity;
}

public int get(int key) {
if(!numToNode.containsKey(key)){
return -1;
}
ListNode node = numToNode.get(key);
moveToTail(node, node.value);
return node.value;
}

public void put(int key, int value) {
if(numToNode.containsKey(key)){//Hash table contains keys
moveToTail(numToNode.get(key), value);
}else{//Hash table does not contain keys
if(numToNode.size() == capacity){//Cache reaches maximum capacity
deleteNode(node);//Two-way list deletes the least recently used node
numToNode.remove(node.key);//Hash Table (Cache) Deletes the least recently used node
}

//Cache did not reach capacity limit
ListNode node = new ListNode(key, value);
insertToTail(node);//Bidirectional Chain List Insert Node
numToNode.put(key, node);//Hash Table (Cache) Insert Node

}

}

//Move the node to the end of the two-way Chain List
private void moveToTail(ListNode node, int newValue){
deleteNode(node);
node.value = newValue;//If you insert a key-value pair, the keys are the same, the values are different, and you want to move the node value updates to the end of the two-way chain table
insertToTail(node);
}

//Delete Node
private void deleteNode(ListNode node){
node.prev.next = node.next;
node.next.prev = node.prev;
}

//Inserts a node at the end of a two-way chain table
private void insertToTail(ListNode node){
tail.prev.next = node;
node.prev = tail.prev;
node.next = tail;
tail.prev = node;
}
}

```

```class LRUCache {
class Node {
int k, v;
Node l, r;
Node(int _k, int _v) {
k = _k;
v = _v;
}
}
int n;
Map<Integer, Node> map;
public LRUCache(int capacity) {
n = capacity;
map  = new HashMap<>();
tail = new Node(-1, -1);
}

public int get(int key) {
if (map.containsKey(key)) {
Node node = map.get(key);
refresh(node);
return node.v;
}
return -1;
}

public void put(int key, int value) {
Node node = null;
if (map.containsKey(key)) {
node = map.get(key);
node.v = value;
} else {
if (map.size() == n) {
Node del = tail.l;
map.remove(del.k);
delete(del);
}
node = new Node(key, value);
map.put(key, node);
}
refresh(node);
}

// The refresh operation is a two-step process:
// 1. First remove the current node from the two-way list (if the node itself exists in the two-way list)
void refresh(Node node) {
delete(node);
}

// delete operation: remove the current node from the two-way chain table
// Since we have pre-established two senders, head and tail, if node.l is not empty, it represents that the node itself exists in a two-way chain table (not a new node)
void delete(Node node) {
if (node.l != null) {
Node left = node.l;
left.r = node.r;
node.r.l = left;
}
}
}
```

This is an improved version of my own code, with a head-to-tail sentry and fewer head-to-end and end-to-end judgments

```class LRUCache {
private int cap;
private int count=0;//Count how many elements are currently stored
private Map<Integer,Node>map=new HashMap();
Node tail=null;//Record the end of a two-way chain table
public LRUCache(int capacity) {
this.cap=capacity;
tail=new Node(-1,-1);
}
public int get(int key) {
if(!map.containsKey(key))
return -1;
Node node=map.get(key);
delete(node.key);
return node.val;
}

public void put(int key, int value) {
Node node=new Node(key,value);
if(map.containsKey(key)){
delete(key);//If there is a current key in the map, remove it first.
}
else {
if(count==cap)
delete(tail.pre.key);
}
}

public void delete(int key){
Node node=map.get(key);
node.pre.next=node.next;
node.next.pre=node.pre;
map.remove(key);
count--;
}

count++;
map.put(node.key,node);
}
}
class Node{
int key;
int val;
Node pre;
Node next;
public Node(int key,int val){
this.key=key;
this.val=val;
}
}
```

```class LRUCache {
int cap;
public LRUCache(int capacity) {
this.cap = capacity;
}

public int get(int key) {
if(!cache.containsKey(key))
return -1;
// Change key to most recently used
makeRecently(key);
return cache.get(key);
}
public void put(int key, int value) {
if (cache.containsKey(key)) {
cache.put(key, value);// Modify the value of key
makeRecently(key); // Change key to most recently used
return;
}
if (cache.size() >= this.cap) {
// The chain header is the oldest unused key
int oldestKey = cache.keySet().iterator().next();
cache.remove(oldestKey);
}

cache.put(key, value);    // Add a new key to the end of the list
}
private void makeRecently(int key)
{
int val= cache.get(key);
cache.remove(key); // Remove the key and reinsert it at the end of the queue
cache.put(key,val);
}
}
```

## 32 Swordfinger Offer II 032. Valid Variants

Given two strings s and t, write a function to determine if they are a set of anaglyphs (heterographic words).

Note: s and T are mutually anaglyphs (ectopic letters) if each character in s and t occurs the same number of times and in a different character order.

First the question can be judged by sorting
Solution ideas: Compare the number of occurrences of each character in two strings, and store them in an array. The character of the first string adds 1 to the corresponding value in the array, the character of the second string subtracts 1 from the corresponding value in the array, and the value in the last array should all be 0. If not, return false

```class Solution {
public boolean isAnagram(String s, String t) {
int n1=s.length();
int n2=t.length();
if(n1!=n2)
return false;
if(s.equals(t))
return false;
int arr[]=new int [128];
for(int i=0;i<n1;i++)
arr[s.charAt(i)-32]++;
for(int i=0;i<n2;i++){
arr[t.charAt(i)-32]--;
if(arr[t.charAt(i)-32]<0)
return false;
}
for(int i=0;i<128;i++){
if(arr[i]%2!=0)
return false;
}
return true;
}
}
```

The Title requires Unicode characters to be processed, so we can consider using a hash table to process them

For advanced problems, Unicode is a solution to the limitations of traditional character encoding, which specifies a unique binary encoding for characters in each language. Unicode may have a character corresponding to more than one byte. In order to let the computer know how many bytes represent a character, the transmission-oriented encoding methods UTF_8 and UTF_16 were gradually used. Specifically relevant knowledge readers can continue to read relevant information to expand their horizons, which will not be expanded here.
Back to this point, the core point of the advanced problem is "Characters are discrete and unknown", so we can just maintain the frequency of corresponding characters with a hash table. At the same time, the reader needs to be aware that Unicode may correspond to more than one byte of a character, and different languages handle string reading differently.

```class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
if(s.equals(t))
return false;
Map<Character, Integer> table = new HashMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
table.put(ch, table.getOrDefault(ch, 0) + 1);
}
for (int i = 0; i < t.length(); i++) {
char ch = t.charAt(i);
table.put(ch, table.getOrDefault(ch, 0) - 1);
if (table.get(ch) < 0) {
return false;
}
}
return true;
}
}

```

# 2021.08.16 11 Hash Table

## 33 Swordfinger Offer II 033. Degeneric Phrases

Solving ideas:

Two strings are heterographic words for each other if and only if they contain the same letter. Strings in the same set of hetero-alphabetic words have the same points. You can use the same points as the flags for a set of hetero-alphabetic words, use a hash table to store each set of hetero-alphabetic words, use the hash table keys as the flags for a set of hetero-alphabetic words, and use the hash table values as a list of hetero-alphabetic words.

Traverse through each string, and for each string, get the flags of the set of alphabetic words in which the string is located, and add the current string to the list of alphabetic words in that set. After traversing all strings, each key-value pair in the hash table is a set of alphabetic words.

```class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>>map=new HashMap();
List<List<String>> list;
for(String s:strs){
char[]arr=s.toCharArray();
Arrays.sort(arr);
String temp=new String(arr);
if(map.containsKey(temp)){
}else{
map.put(temp,new ArrayList());
}
}
return new ArrayList<List<String>>(map.values());
}
}
```

Idea 2: Count

That's great. Count the number of occurrences of each letter, stitch letters and occurrences together into a string as the key value of HashMap. That's great. Value is also a chain table. As long as it's a meta phrase, the strings stitched in alphabetical order and number of occurrences must be equal.

```class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String str : strs) {
int[] counts = new int[26];
int length = str.length();
for (int i = 0; i < length; i++) {
counts[str.charAt(i) - 'a']++;
}
// Each occurrence greater than 0 letters and occurrences are concatenated sequentially into strings as keys to the hash table
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 26; i++) {
if (counts[i] != 0) {
sb.append((char) ('a' + i));
sb.append(counts[i]);
}
}
String key = sb.toString();
List<String> list = map.getOrDefault(key, new ArrayList<String>());
map.put(key, list);
}
return new ArrayList<List<String>>(map.values());
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

## 35 Swordfinger Offer II 035. Minimum time difference

Given a 24-hour time list (hour: minute "HH:MM"), find the minimum time difference between any two times in the list and express it in minutes.

Example 1:
Input: timePoints = ['23:59','00:00']
Output: 1
Example 2:
Input: timePoints = ['00:00','23:59','00:00']
Output: 0

Solve the problem by first converting all the time into an integer value of the number of minutes, up to 24 * 60 = 1440 minutes a day, so if the length of the list exceeds 1440, return directly to 0
After the number of minutes has been calculated, sort, and then calculate the difference between adjacent elements in turn. To get the minimum value, you also need to take the time difference between the minimum value and the maximum value, such as the time difference between 23:59 and 00:01, to compare with the minimum value

```class Solution {
private int parseMinute(String str) {
return str.charAt(0) * 600 + str.charAt(1) * 60 + str.charAt(3) * 10 +str.charAt(4);
}
public int findMinDifference(List<String> timePoints) {
int len = timePoints.size();
if (len < 2 || len > 1440) {
return 0;
}
int[] times = new int[len];
for(int i = 0; i < len; i++) {
times[i] = parseMinute(timePoints.get(i));
}
Arrays.sort(times);
int min = Integer.MAX_VALUE;
for(int i = 0; i < len - 1; i++) {
min = Math.min(min, times[i+1] - times[i]);
if (min == 0) return 0;
}
return Math.min(min, 1440 - times[len-1] + times[0]);
}
}
```

# 2021.08.17 12th Day Stack

## 36 Swordfinger Offer II 036. Suffix expression

Solve the problem by pushing the stack when it encounters an operand, taking out two operands when it encounters an operator, and making the first operand from the later extracted elements

```class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer>stack=new Stack();
int a=0;int b=0;
for(int i=0;i<tokens.length;i++){
String s =tokens[i];
switch(s){
case "+":
a=stack.pop();
b=stack.pop();
stack.push(a+b);
break;
case "-":
a=stack.pop();
b=stack.pop();
stack.push(b-a);
break;

case "*":
a=stack.pop();
b=stack.pop();
stack.push(b*a);
break;

case "/":
a=stack.pop();
b=stack.pop();
stack.push(b/a);
break;

default:
stack.push(Integer.valueOf(s));
}
}
return stack.pop();
}
}
```

Learn, not so many popups

```class Solution {
public int evalRPN(String[] tokens) {
int n = tokens.length;
for (int i = 0; i < n; i++) {
String token = tokens[i];
if (isNumber(token)) {
stack.push(Integer.parseInt(token));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
switch (token) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
default:
}
}
}
return stack.pop();
}

public boolean isNumber(String token) {
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}

}

```

Bye 100% of the code

```class Solution {
public int evalRPN(String[] tokens) {
int[] stack = new int[tokens.length];
int top = -1;

for (String token : tokens) {
switch (token) {
case "+":
stack[top - 1] += stack[top];
top--;
break;
case "-":
stack[top - 1] -= stack[top];
top--;
break;
case "*":
stack[top - 1] *= stack[top];
top--;
break;
case "/":
stack[top - 1] /= stack[top];
top--;
break;
default:
stack[++top] = Integer.valueOf(token);
}
}

return stack[top];
}
}

```

## 37 Swordfinger Offer II 037. Asteroid collisions

The solution, it's all in the code
Positive numbers on the stack, such as negative numbers to touch, always compare the top of the stack, the top of the stack is positive, and the current non-negative number and the top of the stack add up less than 0, pop up the top of the stack, cycle comparison
When the above step no longer pops up, either the stack is empty or the top of the stack is already negative, so we directly stack the current negative number
Or it could be that the current element and the top of the stack add up to zero and pop up the top of the stack directly

```class Solution {
public int[] asteroidCollision(int[] nums) {
int n=nums.length;
int i=0; //Mark planets less than 0 on the left, i planets less than 0 on the left
Stack<Integer>stack=new Stack();
while(i<=n-1&&nums[i]<0){
stack.push(nums[i]);//Add all the negative numbers at the beginning to the stack because they don't collide
i++;
}
for(int cur=i;cur<n;cur++){
if(nums[cur]>0)//Direct stacking of positive numbers
stack.push(nums[cur]);
else{ //negative
while(!stack.isEmpty()&&stack.peek()>0&&nums[cur]+stack.peek()<0){//If the sum is less than 0 and the top of the stack is a positive number, the top element always pops up
stack.pop();
}
if(stack.isEmpty()||(!stack.isEmpty()&&stack.peek()<0)){//Empty stack or negative number at top, stacked
stack.push(nums[cur]);
}
else {//Stack is not empty, nor is the top of the stack a negative number
if(stack.peek()>0&&nums[cur]+stack.peek()==0){//Add equals 0, pop up top of stack
stack.pop();
}
}
}
}
int size=stack.size();
int arr[]=new int[size];
for(int k=size-1;k>=0;k--){
arr[k]=stack.pop();
}
return  arr;
}
}
```

Look at people's code. It's so elegant

```class Solution {
public int[] asteroidCollision(int[] asteroids) {
int[] stack = new int[asteroids.length];
int top = -1;
for(int a:asteroids){
while(a<0&&top>=0&&stack[top]>0&&stack[top]<-a){
top--;
}
if(a<0&&top>=0&&stack[top]>=-a){
if(stack[top]==-a) top--;
continue;//The current negative number is canceled out and does not go on the stack
}
stack[++top] = a;
}
int[] res = new int[top+1];
for(int i = 0;i<=top;i++) res[i] = stack[i];//This is because the ++ top operation results in the last additional element
return res;
}
}
```

## 38 Swordfinger Offer II 038. Daily temperature

Please regenerate a list based on the daily temperature list temperatures and ask the output of its corresponding location to be: At least the number of days to wait to see higher temperatures. If the temperature will not rise after that, replace it with 0 at that location.

Solution ideas: use monotonic stack, arrays there, put the last higher number that is not currently matched on the stack, match to the current array element is larger than the top of the stack, then the corresponding number of days to wait for the top element of the stack is the index of the current array element minus the index of the top element of the stack

How do I find the index of the top element of the stack?
I encapsulate the data and index of each element into a node on the stack, which makes it easy to get the index of that element.
It can also be stored in a one-dimensional array

Finally, when the array is traversed, the number of days to wait for the remaining elements in the stack is zero

```class Solution {
public int[] dailyTemperatures(int[] nums) {
//Using a monotonic stack, but how do I match the index, I encapsulate the index and data into a node and add it to the stack?
Stack<Node>stack=new Stack();
stack.push(new Node(nums[0],0));
for(int i=1;i<nums.length;i++){
while(!stack.isEmpty()&&nums[i]>stack.peek().val){
int index=stack.pop().index;
nums[index]=i-index;
}
stack.push(new Node(nums[i],i));
}
//Finally, when the array is traversed, the number of days to wait for the remaining elements in the stack is zero
while(!stack.isEmpty()){
nums[stack.pop().index]=0;
}
return nums;
}
}
class Node{
int val;
int index;
Node(int val,int index){
this.val=val;
this.index=index;
}
}
```

Am I an hanpi? I save the index when I put it on the stack........

```class Solution {
public int[] dailyTemperatures(int[] nums) {
//Using a monotonic stack, but how do I match the index, I encapsulate the index and data into a node and add it to the stack?
Stack<Integer>stack=new Stack();
stack.push(0);
for(int i=1;i<nums.length;i++){
while(!stack.isEmpty()&&nums[i]>nums[stack.peek()]){
int index=stack.pop();
nums[index]=i-index;
}
stack.push(i);
}
//Finally, when the array is traversed, the number of days to wait for the remaining elements in the stack is zero
while(!stack.isEmpty()){
nums[stack.pop()]=0;
}
return nums;
}
}

```

Idea 2: Dynamic planning
If the current nums[i] is smaller than nums[j], the corresponding j-i is obtained directly, otherwise it is adjusted to the larger number than nums[j]. This is j=j += res[j],res[j] is 0, indicating that there is no greater number behind nums[j]
Come on a quick one

Sequential traversal does not actually make the most efficient use of previous calculations or is a find (reverse order is as simple as predicting the future, so jumping directly is fine)
Reference resources: https://leetcode-cn.com/problems/daily-temperatures/solution/dpde-si-wei-by-ryaninnerpeace-9ib3/

```class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int[] res = new int[temperatures.length];
res[temperatures.length - 1] = 0;
for (int i = temperatures.length - 2; i >= 0; i--) {
for (int j = i + 1; j < temperatures.length; j += res[j]) {
if (temperatures[i] < temperatures[j]) {
res[i] = j - i;
break;
} else if (res[j] == 0) {
res[i] = 0;
break;
}
}
}
return res;
}
}
```

# 2021.08.18 Day 13 Stack

## 39 Swordfinger Offer II 039. Maximum rectangular area of histogram

Solution Idea 1: Enumeration of Violence
The area of the largest histogram that can be exported must be the height of a column. We can find the maximum by using the height of each column as the maximum histogram.

```class Solution {
public int largestRectangleArea(int[] nums) {
int n=nums.length;
Stack<Node>stack=new Stack();
stack.push(new Node(-1,0));//First put the first element on the stack
int max=0;
//The general idea is to enumerate the height of each column as a rectangle, find the area of each rectangle, and then go to the maximum value
//To find the area, you also need to know the width, which is the distance between the first element smaller than the current column and the next one smaller than it.
for(int i=1;i<n;i++){
if(!stack.isEmpty()&&nums[i]<nums[stack.peek().index]){
while(!stack.isEmpty()&&nums[i]<nums[stack.peek().index]){//Possibly the next smaller element of the preceding elements
Node node=stack.pop();
int tempArea=nums[node.index]*(i-node.smallerIndex-1);//We calculated the area of a rectangle that is higher than the current nums[i]
max=Math.max(max,tempArea);
}
if(stack.isEmpty()){//The stack is empty, indicating that the current point is too small, eliminating all the previous ones, the previous smaller element index is -1
stack.push(new Node(-1,i));
}else{
int smallerIndex= (nums[i]==nums[stack.peek().index])?stack.peek().smallerIndex:stack.peek().index;
stack.push(new Node(smallerIndex,i));//How do I find this smallerIndex? When the end of the while, the stack is not empty, and the current element is either greater than or equal to the top of the stack, so the two-minute case above
}
}
else if(!stack.isEmpty()&&nums[i]>nums[stack.peek().index]){
stack.push(new Node(stack.peek().index,i));//If it is greater than the current top of the stack, then the current top of the stack is the previous number smaller than it
}
else if(!stack.isEmpty()&&nums[i]==nums[stack.peek().index]){//If equal to the top of the stack, their previous smaller element is equal
stack.push(new Node(stack.peek().smallerIndex,i));
}
}

while(!stack.isEmpty()){
//If the stack is not empty, then there are no smaller elements left behind. We need to know that the top of the remaining stack must be the last element of the original array, because no one can eliminate it
//So the rest of the stack goes to the end
Node node=stack.pop();
int tempArea=nums[node.index]*(n-node.smallerIndex-1);
max=Math.max(max,tempArea);
}
return max;
}
//Consider encapsulating the current index and the index of the first element smaller than it into a node
class Node{
int smallerIndex;
int index;
Node(int smallerIndex,int index){
this.smallerIndex=smallerIndex;
this.index=index;
}
}
}
```

Array simulation stack, too elegant

```class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] stack = new int[n];
int top = -1;
int res = 0;
for(int i = 0;i<n;i++){
while(top>=0&&heights[stack[top]]>heights[i]){
int r = i;
int l = top>=1?stack[top-1]+1:0;
res = Math.max(res,(r-l)*heights[stack[top]]);
top--;
}
stack[++top] = i;
}
while(top>=0){
int r = n;
int l = top>=1?stack[top-1]+1:0;
res = Math.max(res,(r-l)*heights[stack[top]]);
top--;
}
return res;
}
}
```

# 2021.08.19 Day 14 Pairing

## 41 Swordfinger Offer II 041. Average value of sliding window

Solution ideas: Initialize the container capacity size, and when the number of elements in the queue exceeds the specified container capacity, pop up the queue head element

```class MovingAverage {

/** Initialize your data structure here. */
int size;
double curSum=0.0;
public MovingAverage(int size) {
this.size=size;
}

public double next(int val) {
curSum+=val;
if(queue.size()>size){
curSum-=queue.poll();
}
return (double)curSum/(double)queue.size();
}
}

```

## 42 Swordfinger Offer II 042. Recent requests

```class RecentCounter {

public RecentCounter() {

}

public int ping(int t) {
queue.offer(t);
while(queue.peek()+3000<t){
queue.poll();
}
return queue.size();
}
}
```

## 43 Swordfinger Offer II 043. Add Nodes to Full Binary Tree

Solving ideas:

```class CBTInserter {
TreeNode root;
Deque<TreeNode> deque;
public CBTInserter(TreeNode root) {
this.root = root;
queue.offer(root);

// BFS to populate deque
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left == null || node.right == null)
deque.offerLast(node);
if (node.left != null)
queue.offer(node.left);
if (node.right != null)
queue.offer(node.right);
}
}

public int insert(int v) {
TreeNode node = deque.peekFirst();
deque.offerLast(new TreeNode(v));
if (node.left == null)
node.left = deque.peekLast();
else {
node.right = deque.peekLast();
deque.pollFirst();
}

return node.val;
}

public TreeNode get_root() {
return root;
}
}

```

# 2021.08.2015th Day Queue

## 44 Swordfinger Offer II 044.Maximum per layer of a binary tree

Solution ideas: traverse through the layers, record the maximum value of each layer, write it here first, if I can use dfs for this question, calculate it

```class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer>list=new ArrayList();
if(root==null)
return list;
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
int tempMax=0;
for(int i=0;i<size;i++){
TreeNode temp=queue.poll();
if(i==0)
tempMax=temp.val;
else{
tempMax=Math.max(tempMax,temp.val);
}
if(temp.left!=null)
queue.offer(temp.left);
if(temp.right!=null)
queue.offer(temp.right);
}
}
return list;
}
}
```

```class Solution {
public List<Integer> largestValues(TreeNode root) {
//queue
List<Integer> res = new ArrayList<>();
if(root != null){
}
while(!queue.isEmpty()){
int max = Integer.MIN_VALUE;
int levelSize = queue.size();
for(int i = 0; i < levelSize; i++){
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if(node.left != null){
}
if(node.right != null){
}
}
}
return res;

}
}
```

Idea 2: Deep-first search

That's too strong. If you traverse to the current depth and the list doesn't keep up with the size, you can put the current node's value in the list directly. Otherwise, you can compare the current value with the value that has been sent for the corresponding position in the list. That is, we want to make sure that the size of the list is the same as the maximum depth of the binary tree.

```class Solution {
ArrayList<Integer> res = new ArrayList<>();
public List<Integer> largestValues(TreeNode root) {
dfs(root,0);
return res;
}
public void dfs(TreeNode root , int d){
if(root == null){
return;
}
if(d == res.size()){
}else if(root.val > res.get(d)){
res.set(d,root.val);
}
dfs(root.left , d+1);
dfs(root.right , d+1);
}
}
```

## 45 Swordfinger Offer II 045.The lowest leftmost value of a binary tree

Solution ideas 1: Width first search, temporarily save the first node out of the queue before each layer leaves the queue, until the queue is empty, directly return to the last temporary node value is OK

```class Solution {
public int findBottomLeftValue(TreeNode root) {
List<Integer>list=new ArrayList();
int result=0;
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode temp=queue.poll();
if(temp.left!=null)
queue.offer(temp.left);
if(temp.right!=null)
queue.offer(temp.right);
if(i==0){
result=temp.val;
}
}
}
return result;

}
}
```

Is this sequential traversal not clearer and more concise? Direct reverse, the last node that pops up the barrier is the leftmost node on the last layer

```class Solution {
public int findBottomLeftValue(TreeNode root) {
if (root.left == null && root.right == null) {
return root.val;
}

queue.offer(root);
TreeNode temp = new TreeNode(-100);

while (!queue.isEmpty()) {
temp = queue.poll();

if (temp.right != null) {
// Add the right node to the queue first
queue.offer(temp.right);
}
if (temp.left != null) {
// Add the left node to the queue
queue.offer(temp.left);
}
}

return temp.val;
}
}

```

Idea 2, Depth first, the line finds the maximum depth of the binary tree and finds the first node whose depth equals the maximum depth.
My code is correct only if there is only one node in the last layer, otherwise the last node will be found

```class Solution {
int result=0;
public int findBottomLeftValue(TreeNode root) {
int maxDepth=GetMaxDepth(root);
helper (root,1,maxDepth);
return result;
}
public int GetMaxDepth(TreeNode root){
if(root==null)
return 0;
return 1+Math.max( GetMaxDepth(root.left), GetMaxDepth(root.right));
}
public void helper (TreeNode root,int depth,int maxDepth){
if(root==null)
return ;

if( depth==maxDepth){
result=root.val;
return ;
}
helper (root.left,depth+1,maxDepth);
helper (root.right,depth+1,maxDepth);
}
}
```

Look at someone else's code again

```class Solution {
int maxHeight = -1;
int left = 0;
public int findBottomLeftValue(TreeNode root) {
dfs(root, 0);
return left;
}
void dfs(TreeNode root,int height) {
if(root.left == null && root.right == null) {
if(height > maxHeight) {
maxHeight = height;
left = root.val;
}
return;
}

if(root.left != null) dfs(root.left, height + 1);
if(root.right != null) dfs(root.right, height + 1);

}
}
```

## 46 Swordfinger Offer II 046.Right view of binary tree

Solution Idea 1: Width first search, each time take the last node of each layer into the list

```class Solution {
public List<Integer> rightSideView(TreeNode root) {
//Solving ideas, take the rightmost node of each layer
List<Integer>list=new ArrayList();
if(root==null)
return list;
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode temp=queue.poll();
if(temp.left!=null)
queue.offer(temp.left);
if(temp.right!=null)
queue.offer(temp.right);
if(i==size-1){
}
}
}
return list;
}
}
```

Solving Ideas 2: Deep-first search

We do a deep-first search of the tree, and always access the right subtree first during the search. So for each layer, the first node we see in this layer must be the rightmost node.

We can store the first node at each depth of access, and once we know the number of layers of the tree, we get the final result array

```class Solution {
List<Integer> res=new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
dfs(root,0);
return res;
}
public void dfs(TreeNode root,int depth){
if(root==null) return ;
if(depth==res.size()){
}
dfs(root.right,depth+1);
dfs(root.left,depth+1);
}
}

```

Solving Idea 3: Using Stack
Put the left node on the stack, the right node on the stack, and then the right subtree will be traversed first

```class Solution {
public List<Integer> rightSideView(TreeNode root) {
Map<Integer, Integer> rightmostValueAtDepth = new HashMap<Integer, Integer>();
int max_depth = -1;

Stack<TreeNode> nodeStack = new Stack<TreeNode>();
Stack<Integer> depthStack = new Stack<Integer>();
nodeStack.push(root);
depthStack.push(0);

while (!nodeStack.isEmpty()) {
TreeNode node = nodeStack.pop();
int depth = depthStack.pop();

if (node != null) {
// Maintain the maximum depth of a binary tree
max_depth = Math.max(max_depth, depth);

// If no node of corresponding depth exists, we will insert it
if (!rightmostValueAtDepth.containsKey(depth)) {
rightmostValueAtDepth.put(depth, node.val);
}

nodeStack.push(node.left);
nodeStack.push(node.right);
depthStack.push(depth + 1);
depthStack.push(depth + 1);
}
}

List<Integer> rightView = new ArrayList<Integer>();
for (int depth = 0; depth <= max_depth; depth++) {
}

return rightView;
}
}
```

# Day 16 Tree 2021.08.21

## 49 Swordfinger Offer II 049. Sum of path numbers from root node to leaf node

Solve the problem by recursively traversing, finding the leaf node, splicing the current string onto the leaf node, then adding it to the List, and finally converting the string in the list to an integer sum

```class Solution {
List<String>list=new ArrayList();
public int sumNumbers(TreeNode root) {
helper( root,"");
int result=0;
for(int i=0;i<list.size();i++){
result+=Integer.valueOf(list.get(i));
}
return result;
}
public void helper(TreeNode root,String s){
if(root==null){
return ;
}
if(root.left==null&&root.right==null){
}
helper( root.left,s+root.val);
helper( root.right,s+root.val);
}
}
```

Optimize, recursively with integers directly

```class Solution {
List<Integer>list=new ArrayList();
public int sumNumbers(TreeNode root) {
helper( root,0);
int result=0;
for(int i=0;i<list.size();i++){
result+=list.get(i);
}
return result;
}
public void helper(TreeNode root,int s){
if(root==null){
return ;
}
if(root.left==null&&root.right==null){
}
helper( root.left,s*10+root.val);
helper( root.right,s*10+root.val);
}
}
```

Do not use list

```class Solution {
public int sumNumbers(TreeNode root) {
return dfs(root, 0);
}

public int dfs(TreeNode root, int prevSum) {
if (root == null) {
return 0;
}
int sum = prevSum * 10 + root.val;
if (root.left == null && root.right == null) {
return sum;
} else {
return dfs(root.left, sum) + dfs(root.right, sum);
}
}
}

```

```class Solution {
public int sumNumbers(TreeNode root) {
if (root == null) {
return 0;
}
int sum = 0;
nodeQueue.offer(root);
numQueue.offer(root.val);
while (!nodeQueue.isEmpty()) {
TreeNode node = nodeQueue.poll();
int num = numQueue.poll();
TreeNode left = node.left, right = node.right;
if (left == null && right == null) {
sum += num;
} else {
if (left != null) {
nodeQueue.offer(left);
numQueue.offer(num * 10 + left.val);
}
if (right != null) {
nodeQueue.offer(right);
numQueue.offer(num * 10 + right.val);
}
}
}
return sum;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

# 2021.08.22 17th Day Tree

## 50 Swordfinger Offer II 050.Sum of Downward Path Nodes

Solution ideas: use prefix sum, calculate to the current node, check whether there is a prefix before and curSum-target
Reference resources: Prefix and, Recursive, Backward

```class Solution {
int result;
Map<Integer,Integer>map=new HashMap();
public int pathSum(TreeNode root, int targetSum) {
if(root==null)
return 0;
map.put(0,1); //Don't forget, or you'll undercount
helper(root,targetSum,0);
return result;
}
public void helper(TreeNode root,int targetSum,int curSum){
if(root==null)
return ;
curSum+=root.val;
result+=map.getOrDefault(curSum-targetSum,0);//Note that you cannot change the position of the following sentence, otherwise [1], 0 would not work
map.put(curSum,map.getOrDefault(curSum,0)+1);
helper(root.left, targetSum, curSum);
helper(root.right, targetSum, curSum);
map.put(curSum,map.get(curSum)-1);
}
}
```

## 52 Swordfinger Offer II 052. Flattening a Binary Search Tree

Solution Idea 1: Traverse through all the nodes in a middle order (recursion, iteration), put them in a list, and then take them out in turn

Solution Idea 2: Recursively, create a false header node, in the middle of the traversal process, continuously add the traversed nodes behind the false header

```class Solution {
public TreeNode increasingBST(TreeNode root) {
inorder(root);
}
public void inorder(TreeNode node) {
if (node == null) {
return;
}
inorder(node.left);
pre.right = node;
pre = node;
pre.left = null;
inorder(node.right);
}
}
```

# 2021.08.24 19th Day Tree

## 56 Swordfinger Offer II 056.Sum of two nodes in a binary search tree

Given the root node root and an integer k of a binary search tree, determine if there are two nodes in the binary search tree whose values sum to equal K. Assume that the values of the nodes in the binary search tree are unique.

Example 1:

Input: root = [8,6,10,5,7,9,11], k = 12
Output: true
Interpretation: The sum of Node 5 and Node 7 equals 12

Example 2:

Input: root = [8,6,10,5,7,9,11], k = 22
Output: false
Interpretation: There is no node with a sum of two node values of 22

Solve the problem by traversing in middle order and saving the traversed node values with set

```class Solution {
Set<Integer>set=new HashSet();
public boolean findTarget(TreeNode root, int k) {
if(root==null){
return false;
}
if(set.contains(k-root.val)){
return true;
}
return  findTarget( root.left,  k)||findTarget( root.right,  k);
}
}
```

## 57 Swordfinger Offer II 057. The difference between value and subscript is within a given range

Give you an array of integers nums and two integers k and t. Determine if there are two different subscripts I and j so that ABS (nums[i] - nums[j]) <= t satisfies ABS (i - j) <= k.

Returns true if it exists, false if it does not exist.

Example 1:

Input: nums = [1,2,3,1], k = 3, t = 0
Output:true

Example 2:

Input: nums = [1,0,1,1], k = 1, t = 2
Output:true

Example 3:

Input: nums = [1,5,9,1,5,9], k = 2, t = 3
Output: false

Solution Idea 1: Violence, Can't Solve

```class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
int n=nums.length;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
long a=Math.abs((long)nums[i] - (long)nums[j]);
if((a <= t)&& Math.abs(i - j) <= k)
return true;
}
}
return false;
}
}
```

Solving Ideas 2: Reference Gongshui Trifoliate: A Double Solution: "Sliding Window & Bisection" & "Bucket Sorting" Solution

```class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
int n = nums.length;
TreeSet<Long> ts = new TreeSet<>();
for (int i = 0; i < n; i++) {
Long u = nums[i] * 1L;
// Find the maximum value less than or equal to u from ts (the number nearest to u less than or equal to u)
Long l = ts.floor(u);
// Find the minimum value greater than or equal to u from ts (the number nearest to u greater than or equal to u)
Long r = ts.ceiling(u);
if(l != null && u - l <= t) return true;
if(r != null && r - u <= t) return true;
// Add the current number to ts and remove the number whose subscript range is not [max (0, I - k), i] (keep the sliding window size k)
if (i >= k) ts.remove(nums[i - k] * 1L);
}
return false;
}
}

```
```class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
int len = nums.length;
int[][] data = new int[len][2];
for (int i = 0; i < len; i++) data[i] = new int[]{nums[i], i};
Arrays.sort(data, Comparator.comparingInt(a -> a[0])); // Sort element values in ascending order
for (int i = 0; i < len - 1; i++) {
// Fixed the first number
for (int j = i + 1; j < len; j++) {
if ((long) data[j][0] - data[i][0] > t) break;
if (Math.abs(data[j][1] - data[i][1]) <= k) return true;
}
}
return false;
}
}
```

# 2021.08.25 20th heap

## 59 Swordfinger Offer II 059. Largest K Value of Data Flow

Design a class that finds the kth largest element in the data flow. Note that the kth largest element is sorted, not the kth different element.

Implement the KthLargest class:

```KthLargest(int k, int[] nums) Use integers k And integer flow nums Initialize the object.
int add(int val) take val Insert Data Stream nums After that, return to the k Large elements.
```

Example:

Input:
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
Output:
[null, 4, 5, 5, 8, 8]

Explanation:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);

Source: LeetCode

Having written for half a day, it would be better to have a priority queue.

```class KthLargest {
int nums[];
int k;
int max=Integer.MIN_VALUE;
public KthLargest(int a, int[] arr) {
nums=new int[k];
for(int i=0;i<k;i++){
nums[i]=arr[i];
}
k=a;
buildHeap(nums,k);
for(int i=k;i<nums.length;i++){
if(nums[i]>nums[0]){
swap(nums,0,i);
heaplify( nums,0,k);
}
}
}

if(nums.length<k){

return   Math.max(max,val);
}
if(val>nums[0]){
nums[0]=val;
heaplify(nums,0,k);
}
return nums[0];
}
public void buildHeap(int nums[],int k){
for(int i=nums.length/2-1;i>=0;i--){
heaplify(nums,i,k);
}
}
public void heaplify(int nums[],int i,int k){
int minIndex=i;
while(true){
if(i*2+1<k&&nums[i*2+1]<nums[minIndex]) minIndex=i*2+1;
if(i*2+2<k&&nums[i*2+2]<nums[minIndex]) minIndex=i*2+2;
if(i==minIndex) break;
swap(nums,i,minIndex);
i=minIndex;
}
}
public void swap(int nums[],int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}

/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
*/
```

Really Absolute

```class KthLargest {
PriorityQueue<Integer> pq;
int k;

public KthLargest(int k, int[] nums) {
this.k = k;
pq = new PriorityQueue<Integer>();
for (int x : nums) {
}
}

pq.offer(val);
if (pq.size() > k) {
pq.poll();
}
return pq.peek();
}
}

```

## 60 Swordfinger Offer II 060. The k most frequently occurring digits

Given an array of integers nums and an integer k, return the element with the highest K frequency before it appears. The answer can be returned in any order.

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Solving ideas:

```  class Solution {
Map<Integer,Integer>map=new HashMap();
//Solving ideas, hash table + heap, number of occurrences of hash table statistics, number of occurrences of heap maintenance k digits
public int[] topKFrequent(int[] nums, int k) {
for(int i=0;i<nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
Set entrySet=map.entrySet();
Map.Entry entry[]=new Map.Entry [k];
int cur=0;
for(Object ent:entrySet){
if(cur<k)
entry[cur++]=  (Map.Entry)ent;
else
break;
}
buildHeap(entry,k);//Create a heap of size k first
cur=0;
for(Object ent:entrySet){
if(cur>=k){
Map.Entry m=(Map.Entry)ent;
if((int)m.getValue()>(int)entry[0].getValue()){
entry[0]=m;
heapify(entry, 0, k);
}
}
cur++;
}
int res[]=new int[k];
for(int i=0;i<k;i++){
res[i]=(int)entry[i].getKey();
}
return res;
}
public void  buildHeap(Map.Entry entry[], int k){
for(int i=k/2-1;i>=0;i--){
heapify(entry,i,k);
}
}
public void heapify(Map.Entry entry[],int i,int k){
int minIndex=i;
while(true){
if(i*2+1<k&&(int)entry[i*2+1].getValue()<(int)entry[minIndex].getValue())  minIndex=i*2+1;
if(i*2+2<k&&(int)entry[i*2+2].getValue()<(int)entry[minIndex].getValue())  minIndex=i*2+2;
if(minIndex==i) break;
swap(entry,i,minIndex);
i=minIndex;
}
}
public void swap( Map.Entry entry[],int i,int j){
Map.Entry temp=entry[i];
entry[i]=entry[j];
entry[j]=temp;
}
}
```

Priority Queue

```class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
for (int num : nums) {
occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
}

// The first element of int[] represents the value of the array, and the second element represents the number of times the value occurs
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] m, int[] n) {
return m[1] - n[1];
}
});
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (queue.size() == k) {
if (queue.peek()[1] < count) {
queue.poll();
queue.offer(new int[]{num, count});
}
} else {
queue.offer(new int[]{num, count});
}
}
int[] ret = new int[k];
for (int i = 0; i < k; ++i) {
ret[i] = queue.poll()[0];
}
return ret;
}
}

Author: LeetCode-Solution
Source: Force buckle ( LeetCode)
```

## 61 Swordfinger Offer II 061. and minimum k pairs

Given two arrays of integers nums1 and nums2 in ascending order, and an integer k.

Define a pair of values (u,v), where the first element comes from nums1 and the second from nums2.

Please find the minimum k pairs (u1,v1), (u2,v2)... (uk,vk).

Example 1:

Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
Output: [1,2], [1,4], [1,6]
Interpretation: Returns the first 3 logarithms in the sequence:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

Example 2:

Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
Output: [1,1], [1,1]
Interpretation: Returns the first 2 logarithms in the sequence:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]

Example 3:

Input: nums1 = [1,2], nums2 = [3], k = 3
Output: [1,3], [2,3]
Interpretation: It is also possible that all pairs of numbers in the sequence are returned: [1,3], [2,3]

Source: LeetCode

Solving ideas, using priority queues, big root heaps

```class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
//Solving problems, priority queue to build big root heap
List<List<Integer>>list=new ArrayList();
PriorityQueue<int[]>queue=new PriorityQueue<int[]>((int []a,int[]b)->(b[0]+b[1])-(a[0]+a[1]));//Note how the comparator is written. By default, it is a small root heap. Constructing a large root heap requires defining a constructor.
for(int i=0;i<nums1.length;i++){
for(int j=0;j<nums2.length;j++){
int temp[]=new int[]{nums1[i],nums2[j]};
if(queue.size()<k){
queue.offer(temp);
}else{
if(temp[0]+temp[1]<queue.peek()[0]+queue.peek()[1]){
queue.poll();
queue.offer(temp);
}else{
break;//Notice the ascending order
}
}
}
}
//int size=queue.size();
for(int i=0;i<k;i++){
if(!queue.isEmpty()){
int temp1[]=queue.poll();
List<Integer> list1 = Arrays.asList(temp1[0],temp1[1]);
}
}
return list;
}
}
```

```class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> res = new ArrayList<>();
PriorityQueue<int[]> pq = new PriorityQueue<>(k, (o1, o2)->(o2[0] + o2[1] - o1[0] - o1[1]));
for(int i = 0; i < Math.min(nums1.length, k); i++){
for(int j = 0; j < Math.min(nums2.length, k); j++){
if(pq.size() == k && nums1[i] + nums2[j] >= pq.peek()[0] + pq.peek()[1]) break;
if(pq.size() == k) pq.poll();
pq.offer(new int[]{nums1[i], nums2[j]});
}
}
for(int i = 0; i < k && pq.size() > 0; i++){
int[] temp = pq.poll();
List<Integer> list = new ArrayList<>();
}
return res;
}
}

```

Posted by kusal on Sun, 31 Oct 2021 14:09:29 -0700