1. Where the dream begins - the sum of two numbers

Given an integer array nums and an integer target value target, please find the two integers with and as the target value target in the array and return their array subscripts.

You can assume that each input will correspond to only one answer. However, the same element in the array cannot be repeated in the answer.

You can return answers in any order.

class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { int i,j; for(i=0;i<nums.size()-1;i++) { for(j=i+1;j<nums.size();j++) { if(nums[i]+nums[j]==target) return {i,j}; } } return {i,j}; }; };

It's a very simple violent loop, but I've seen the inner loop return for the first time. The topic said to design an algorithm with a time complexity less than n^2. Let's try it.

class Solution{ public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> twoSum; map<int, int> tmpmap;//The key value is the value of nums, and the variable value is the subscript of nums for (int i = 0; i < nums.size(); i++) { tmpmap[nums[i]] = i; } for (int i = 0; i < nums.size(); i++) { if (tmpmap.count(target - nums[i]) != 0 && tmpmap[target-nums[i]]!=i) {// If the subscript corresponding to the target value minus the looped value is not 0 or i, //[if there is another number added to the loop value equal to target, the result will be returned] twoSum.push_back(i); twoSum.push_back(tmpmap[target - nums[i]]); break; } } return twoSum; } };

Note: count and find methods in Map

Using count, the number of elements to be found is returned. If yes, return 1; Otherwise, 0 is returned. Note that the same element does not exist in the map, so the return value can only be 1 or 0.

Using find, the location of the element to be found is returned. If not, map.end() is returned.

This method uses hash table to directly find possible solutions through key value pairs in word cycle, with low time complexity.

2. Add two numbers

Give you two non empty linked lists to represent two non negative integers. They store each number in reverse order, and each node can store only one number.

Please add the two numbers and return a linked list representing sum in the same form.

You can assume that neither number starts with 0 except the number 0.

After reading some example solutions, I can't help feeling that this problem is so strange. It's not necessary to save two ordinary integers in the linked list structure. It can be solved by one addition

Non recursive solution:

1. Bit by bit addition and carry of linked list elements

2. Find the integers represented by the two linked lists, add them and store the results in the new linked list

Non recursive solution

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* head=new ListNode(-1);//Create a chain header to return results ListNode* h=head;//Move pointer int sum=0; bool carry=false; while(l1!=NULL||l2!=NULL) { if(l1!=NULL) { sum+=l1->val; l1=l1->next; } if(l2!=NULL) { sum+=l2->val; l2=l2->next; } if(carry) { sum++; carry=false; } if(sum>9) carry=true; h->next=new ListNode(sum%10); h=h->next; sum=0; } if(carry) { h->next=new ListNode(1); } head=head->next; return head; } };

3. Longest substring without repeated characters

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

Official explanation:

Sliding window method:

1. Use two pointers to represent the left and right boundaries of the substring

2. Use the C + + data structure std::unordered_set (hash set) determines whether there are duplicate characters

Time complexity is O(n^2)

Firstly, the non repeating substring with the left pointer at position 0 is obtained. Move the left pointer to the right, delete the last actual element in occ, and continue to move the right pointer to find the maximum length of this round.

Update each round until the left pointer moves to the last element.

class Solution { public: int lengthOfLongestSubstring(string s) { // A hash set that records whether each character has occurred unordered_set<char> occ; int n = s.size(); // The right pointer, whose initial value is - 1, is equivalent to that we are on the left side of the left boundary of the string and have not started moving int rk = -1, ans = 0; // Enumerates the position of the left pointer, and the initial value is implicitly expressed as - 1 for (int i = 0; i < n; ++i) { if (i != 0) { // The left pointer moves one space to the right to remove a character occ.erase(s[i - 1]); } while (rk + 1 < n && !occ.count(s[rk + 1])) { // Keep moving the right pointer occ.insert(s[rk + 1]); ++rk; } // Characters i to rk are a very long non repeating character string ans = max(ans, rk - i + 1); } return ans; } };

Big brother's solution seen in the comment area

Said he beat 100% of the people

int lengthOfLongestSubstring(char * s){ int start = 0, end = 0, maxlen = 0; char map[256] = {0}; map[(int)*(s+start)] = 1; while( *(s+end) != 0 ) { maxlen = maxlen>(end-start+1)?maxlen:(end-start+1); ++end; while( 0 != map[ (int)*(s+end) ] )//The new element to be added conflicts with the element in the map { map[ (int)*(s+start) ] = 0; ++start; } map[(int)*(s+end)] = 1; } return maxlen; }

Clear and strange ideas

Maintain a character table in which existing characters are stored, (int)*(s+end) is the ASCII code of the corresponding character, start is the beginning and end of the string.

I didn't understand it. It's better to slide the windows left and right

I hope I can understand it one day

4. Find the median of two positively ordered arrays

Can you design an algorithm with time complexity O(log (m+n)) to solve this problem?

My simple idea

1. Array merging

2. Use the sorting algorithm in algorithm

3. Find the median

class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { vector<int>num ; num.insert(num.end(),nums1.begin(),nums1.end()); num.insert(num.end(),nums2.begin(),nums2.end()); double ans=0; sort(num.begin(),num.end()); if(num.size()%2==0) ans=double(num[num.size()/2]+num[num.size()/2-1])/2; else ans=num[num.size()/2]; return ans; } };

Evaluation results

Memory is a little abusive

The time complexity of fast scheduling is O(nlogn)

The advanced requirement is O(log(m+n)), go to the comment area to find a good solution, and see the algorithm and ideas of the top man in the comment area.

1.O(log(m+n)) is associated with binary search method

2. Find the median trick: find the (m+n+1)/2 and (m+n+2)/2, and find the average of the two numbers.

3. Implement a function to find the k-th element in two ordered arrays to avoid generating new arrays and increasing space complexity

Implementation of 3: use two variables i and j to mark the starting positions of nums1 and nums2 respectively

1. Boundary problem: when the starting position of an array is greater than its array length, it means that some numbers have been eliminated, which is equivalent to an empty array. You can directly find numbers in another array. Or recursion to k=1, just compare the values of nums1 and nums2 to find the K element

2. Generally, the recursive method of gradually reducing the scope is adopted to divide K into two parts. Find the k/2 element in nums1 and nums2 respectively. Check whether an array does not have k/2 elements in advance. If so, the first k/2 elements of another array can be eliminated directly.

If the K/2 number of the first array is small, it means that the number we are looking for is certainly not the first K/2 number in nums1, so we can eliminate it, move the starting position of nums1 backward by K/2, and the K at this time also subtracts K/2, and call recursion.

class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length; int n = nums2.length; int left = (m + n + 1) / 2; int right = (m + n + 2) / 2; return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0; } //i: Start position of nums1 J: start position of nums2 public int findKth(int[] nums1, int i, int[] nums2, int j, int k){ if( i >= nums1.length) return nums2[j + k - 1];//nums1 is an empty array if( j >= nums2.length) return nums1[i + k - 1];//nums2 is an empty array if(k == 1){ return Math.min(nums1[i], nums2[j]); } int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE; int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE; if(midVal1 < midVal2){ return findKth(nums1, i + k / 2, nums2, j , k - k / 2); }else{ return findKth(nums1, i, nums2, j + k / 2 , k - k / 2); } } }

September 19, 2021

The first four questions are sorted out

Sure enough, I am addicted to design and mind teacher

We must stick to it