Fundamentals of algorithm - array

catalogue

Knowledge points:

Algorithm:

1. Binary search (loop invariant principle)

Example 1: leetcode 704 binary search

Example 2: leetcode 34. Find the first and last positions of elements in the sorted array

Example 3: leetcode 69   Square root of x, using binary search

2. Double pointer

Example 1: leetcode   27. Remove element

Example 2: leetcode   26. Delete duplicates in the ordered array

Example 3: leetcode   977. Square of ordered array

3. Sliding window

Example 1: leetcode   209. Minimum length subarray

Example 2: leetcode   904. Fruit baskets

Knowledge points:

  • An array is a collection of data of the same type stored in a continuous memory space.
  • The array subscript starts from 0;
  • The addresses of array memory space are continuous. When deleting or adding elements, the addresses of other elements should be moved.
  • The elements of the array cannot be deleted, but can only be overwritten.
  • The difference between vector and array: the underlying implementation of vector is array, and vector is a container, not an array.

Algorithm:

1. Binary search (loop invariant principle)

Key: handle the boundary according to the definition of search interval.

Preconditions for binary search: an ordered array and no duplicate elements in the array.

There are generally two types of interval definitions: left closed right open, left closed right closed.

Example 1: leetcode 704 binary search

Given an n-element ordered (ascending) integer array nums and a target value target  , Write a function to search the target in nums. If the target value exists, return the subscript. Otherwise, return - 1.

#include<iostream>
using namespace std;
#include<vector>

int search(vector<int>&nums, int target) {
	int left = 0;
	int right = nums.size() - 1;//Define the target in the [left,right] left closed right closed interval
	while (left <= right) {
		int middle = left + (right - left) / 2;//Prevent overflow, = = (right - left) / 2
		if (nums[middle] < target) {
			left = middle + 1;
		}
		else if (nums[middle] > target) {
			right = middle - 1;
		}
		else {
			return middle;
		}
	}
	return -1;
}
int main() {
	cout << "Please enter the number of elements of the array: ";
	int n;
	while (cin >> n) {
		vector<int> nums(n);
		for (int i = 0; i < n; i++) cin >> nums[i];

		cout << "Please enter the target value (integer): " ;
		int target;
		cin >> target;

		if (search(nums, target) == -1) {
			cout << "There are no elements in the array equal to the target value." << endl;
		}
		else {
			cout << "The subscripts of the elements in the array equal to the target value are: " ;
			cout<<search(nums, target)<<endl;
		}
		
	}
	system("pause");
	return 0;
}

Supplement: < < 1, shifting left by 1 bit is equivalent to multiplying by 2; > > 1. Shifting 1 bit to the right is equivalent to dividing by 2;

Example 2: leetcode 34. Find the first and last positions of elements in the sorted array

Given an integer array nums arranged in ascending order and a target value target. Find the start and end positions of the given target value in the array.

If the target value target does not exist in the array, return   [-1, -1].

Idea:

First position: the first position in the array equal to target

Last position: the last position in the array greater than the target element minus 1;

int search4(vector<int>&nums, int target,bool lf) {//bool lf is used to determine whether the calculation is a left pointer or a right pointer
	int left = 0;
	int right = nums.size() - 1;//Define the target in the [left,right) left closed right open interval
	int result = nums.size();//For example, the array is [7,7,8,8], and the target value is 8. In fact, it cannot enter the if statement, that is, the result value will not change, so it is set as the array length at the beginning, and the subscript value obtained at the end is reduced by 1
	while (left <= right) {
		int middle = left + (right - left) / 2;//Prevent overflow, = = (right - left) / 2
		if ((nums[middle] >= target  && lf) || nums[middle]>target) {
			right = middle - 1; //target is in the right interval, [middle+1, right)
			result = middle;
		}
		else{
			left = middle + 1;//target is in the left interval, [left,middle)
		}
	}
	return result;
}
vector<int> serchFirstAndLast(vector<int>&nums, int target) {
	int leftptr = search4(nums, target, true);
	int rightptr = search4(nums, target, false)-1;
	if (leftptr <= rightptr && rightptr <nums.size() && nums[leftptr]==target && nums[rightptr] == target) {
		return vector<int> { leftptr, rightptr };
	}
	return vector<int> { -1, -1 };
}

Example 3: leetcode 69   Square root of x, using binary search

int mySqrt(int x) {
	int l = 1, r = x, result = x;
	while (l <= r) {
		int mid = l + (r - l) / 2;
		if ( mid*mid <= x) {
			l = mid + 1;
			result = mid;
		}
		else {
			r = mid - 1;
		}
	}
	return result;
}

2. Double pointer

Double finger needle method: complete the work of two for loops under one for loop through a fast pointer and a slow pointer.

Example 1: leetcode   27. Remove element

Give you an array nums   And a value Val, you need to remove all values in place equal to   val   And returns the new length of the array after removal.

Instead of using extra array space, you must use only O(1) extra space and modify the input array in place.

The order of elements can be changed. You don't need to consider the elements in the array beyond the new length.

#include<iostream>
using namespace std;
#include<vector>

int removeElement2(vector<int>& nums, int val) {
	int slow = 0;//Slow pointer
	for (int i = 0; i < nums.size(); i++) {
		//If it is equal to the target value, the fast pointer moves forward. If it is not equal, the slow pointer and the fast pointer move at the same time
		if (nums[i] != val) {
			nums[slow++] = nums[i];
		}
	}
	return slow;
}
int main() {
	cout << "Please enter the number of elements of the array: ";
	int n;
	while (cin >> n) {
		vector<int> nums(n);
		for (int i = 0; i < n; i++) cin >> nums[i];

		cout << "Please enter the target value (integer): ";
		int target;
		cin >> target;

		//Removing Elements 
		int len = removeElement2(nums, target);
		cout << "The array length after removing elements is:"<< len <<endl;
		for (int i = 0; i < len; i++) {
			cout<< nums[i] <<" ";
		}
	system("pause");
	return 0;
}

Example 2: leetcode   26. Delete duplicates in the ordered array

The core code is as follows:

int removeDuplicates(vector<int>& nums) {
	int n = nums.size();
	if (n == 0) return 0;
	int slow = 0;
	for (int i = 0; i < n; i++) {
		if (nums[slow] != nums[i]) {
			nums[++slow] = nums[i];
		}
	}
	return slow + 1;
}

Example 3: leetcode   977. Square of ordered array

Give you an integer array nums sorted in non decreasing order, and return a new array composed of the square of each number. It is also required to sort in non decreasing order.

    vector<int> sortedSquares(vector<int>& nums) {
	    int first = 0, last = nums.size() - 1;
	    vector<int> v(last+1,0);
	    for(int i=last;i>=0;i--) {
		    if (nums[first] * nums[first] > nums[last] * nums[last]) {
			    v[i] = nums[first] * nums[first];
			    first++;
		    }
		    else {
			    v[i] = nums[last] * nums[last];
			    last--;
		    }
	    }
	    return v;
    }

3. Sliding window

Constantly adjust the start position and end position of the subsequence, so as to get the desired results.

Sliding window is mainly used on arrays and strings.

Example 1: leetcode   209. Minimum length subarray

int minSubArrayLen(int target, vector<int>& nums) {
	int n = nums.size();
	int first = 0;//Start position of sliding window
	int subLength = 0;//Subarray length
	int sum = 0;//Sum of subarrays
	int result = INT32_MAX;//The default is the maximum value at the beginning
	for (int i = 0; i < n; i++) {
		sum += nums[i];
		while (sum >= target) {
			//When the sum of subarrays is greater than or equal to the target value, the starting position of the sliding window needs to move forward
			subLength = i - first + 1;
			result = result < subLength ? result : subLength;
			sum -= nums[first];
			first++; //Continuously change the starting position of the subsequence
		}
	}
	// If the result is not assigned, it returns 0, indicating that there are no qualified subsequences
	return result==INT32_MAX ? 0 : result;
}

Example 2: leetcode   904. Fruit baskets

First of all, we have to find out the requirements of this problem: find the longest subarray with only two types, and return its length

int totalFruit(vector<int>& fruits) {
	int first = 0, second = 0;
	int len = 0;
	int subLen = 0;
	int temp = 0;//You need a variable to record which subscript should start when the third element appears.
	for (int i = 0; i < fruits.size(); i++) {
		if (fruits[first] != fruits[i] && fruits[second] != fruits[i])
		{
			if (fruits[first] != fruits[second]) {
				first = temp;
			}
			second = i;
		}
		if (fruits[temp] != fruits[i]) {
			temp = i;
		}
		subLen = i - first + 1;
		len = len < subLen ? subLen : len;
	}
	return len;
}

Keywords: C++ Algorithm leetcode

Added by always_confused on Wed, 15 Sep 2021 00:29:49 +0300