Algorithm brushing questions - array

Search in JZ4 two-dimensional array

**Title description:** In a two-dimensional array (each one-dimensional array has the same length), each row is sorted in ascending order from left to right, and each column is sorted in ascending order from top to bottom. Please complete a function, input such a two-dimensional array and an integer, and judge whether the integer is contained in the array.

Solutions:

Normal: double loop, search one by one; [but this linear search method is extremely inefficient]

Advanced: According to the conditions given in the title (increase from left to right, and increase from top to bottom), we can start comparison from the upper right corner (or lower left corner) so that we can exclude one row or one column at a time.

for example

1 2 3
2 3 4
4 5 6  //查找5
//右上角:是所在行的最大值,所在列的最小值
//3比5小 ==> 列++
//4比5小 ==> 列++
//6比5大 ==> 行--

In this process, care should be taken to avoid the array subscript out of bounds, so the condition of the loop is more important

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int row = array.size();//行
        int col = array[0].size();//列
        //array[i][j]
        int i = 0, j = col - 1;//用右上角的值来比较
        while(i < row && j >= 0)
        {
            //比右上角的值大,行++
            if(target > array[i][j]) i++;
            //比右上角的值小,列--
            else if(target < array[i][j]) j--;
            else if(target == array[i][j]) return true;
        }
        //走到这说明找不到
        return false;
    }
};

Minimum number of JZ11 rotation arrays

**Title description:** There is a non-descending array of length n, such as [1,2,3,4,5], rotate it, that is, move the first few elements of an array to the end of the array , into a rotation array, such as [3,4,5,1,2], or [4,5,1,2,3]. Excuse me, given such a rotation array, find the minimum value in the array.

Problem-solving ideas :

Normal: 1. Traverse the array to find the minimum value [the efficiency of the linear search method is too low]; 2. Double pointer, compare the size of the current value and the next value at the same time. [Time complexity is the same as 1, no performance improvement]

Advanced: Learn from the idea of ​​binary search. After an array is rotated, the result can be regarded as two new non-descending arrays. What we need to do is to find the split position of the two new arrays, and by continuously shrinking [left, right ] Finalize the min!

left, right, mid three subscripts,

  1 2 3 4 5//非降序数组
//情况1
  2    3    4    5    1
left       mid       right
此时a[left]<=a[mid],说明前半段是非降序数组;a[right]<a[mid],说明后半段顺序是不对的,那么对后半段再次进行查找
  2    3    4    5    1
          left  mid   right
此时a[left]<=a[mid],说明前半段是非降序数组;a[right]<a[mid],说明后半段顺序是不对的,那么对后半段再次进行查找
  2    3    4    5    1
             left/mid right
此时left==mid,说明right所指向的就是最小值

Induction: When a[left]<=a[mid], the second half should be searched

//情况2
  5    1    2    3    4//旋转后
left       mid       right
此时a[left]>a[mid],说明前半段顺序是不对的;a[right]>a[mid],说明后半段是非降序数组,那么对前半段再次进行查找
  5    1    2    3    4//旋转后
left  mid   right
此时a[left]>a[mid],说明前半段顺序是不对的;a[right]>a[mid],说明后半段是非降序数组,那么对前半段再次进行查找
  5       1    2    3    4//旋转后
left/mid right
此时left==mid,说明right所指向的就是最小值

Induction: When a[left]>a[mid], you need to search for the first half

There is an implicit relationship: when (left==mid)> (left+1right) ==> right points to the minimum value.

In non-decreasing sorting , a[left]==a[mid]==a[right] may occur , and we cannot determine whether the minimum value is on the left or right of mid, so linear traversal is required.

  1    1    1    0    1//旋转后
left       mid       right

The general loop condition is rotateArray[left] >= rotateArray[right] (the one that can enter the loop must be the rotated array!), mid=0 before entering the loop, so that we can guarantee to encounter 1 2 2 2 (unrotated array) In this case, it can still be judged

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.empty()) return 0;
        int left = 0;
        int right = rotateArray.size() - 1;
        int mid = 0;//如果这个数组是1 2 2 2没有旋转的数组,就是mid

        while(rotateArray[left] >= rotateArray[right])//保证该数组是旋转过的数组
        {
            if(right - left == 1)//两个下标相邻,右索引就是最小值
            {
                mid = right;
                break;
            }
            mid = (right + left) / 2;
            //如果无法判断大小,就线性遍历搜索最小值
            if(rotateArray[left] == rotateArray[mid] && rotateArray[right] == rotateArray[mid])
            {
                int min = rotateArray[left];
                for(int i = left + 1; i <= right; i++)
                {
                    if(rotateArray[i] < min)
                    {
                        min = rotateArray[i];                        
                    }
                }
                //遍历结束,返回最小值
                return min;
            }
            
            if(rotateArray[mid] >= rotateArray[left]) left = mid;//搜索后半段
            else right = mid;//搜索前半段
        }
        return rotateArray[mid];
    }
};

Adjust the order of the array so that odd numbers come before even numbers

Input an array of integers, implement a function to adjust the order of the numbers in the array, so that all odd numbers are located in the first half of the array, all even numbers are located in the second half of the array, and the relative relationship between odd numbers and odd numbers, even numbers and even numbers is guaranteed The position is unchanged. Such as 1 2 3 4 5 6

Key points: the relative position remains unchanged, get 1 3 5 2 4 6

Problem-solving ideas :

Normal: 1. Change the relative position. Head and tail double pointers, when the head pointer encounters an odd number, ++ stops and exchanges when it encounters an even number; when the tail pointer encounters an even number, it stops and exchanges. 2. Do not change the relative position. new Two arrays, traverse the original array, one array holds odd numbers, one array holds even numbers, after traversing, add the data of the even number array to the back of the odd number array.

Advanced: Learn from the idea of ​​insertion sort. Start traversing from the beginning, and when encountering an odd number, start from the current position and move from the back to the front, until the last odd number, leaving a space for the current odd number to insert. Covering move, just overwrite the current odd number, avoiding data redundancy

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        int k = 0;
        for(int i = 0; i < array.size(); i++)
        {
            if(array[i] & 1)//奇数
            {
                int tmp = array[i];//保存奇数,后续进行覆盖挪动
                int j = i;//从当前下标开始挪动,所以当前下标位置的数据会被覆盖
                while(j > k)
                {
                    array[j] = array[j-1];
                    j--;
                }
                array[k++] = tmp;
            }
        }
    }
};

Numbers that appear more than half of the time in the JZ39 array

Title description : There is a number in the array that appears more than half of the length of the array, please find this number. For example, input an array {1,2,3,2,2,2,5,4,2} with a length of 9. Since the number 2 appears 5 times in the array, which exceeds half the length of the array, 2 is output. Output 0 if not present.

Problem-solving ideas :

Idea 1: Define map, use the mapping relationship of <number, number of times>, and finally count the number of occurrences of each character.

Idea 2: Sort, the number with the most occurrences must be in the middle. Then check whether the number of occurrences of the numbers in the middle meets the requirements.

Idea 3: Since the target data exceeds half the length of the array, we remove two different numbers at the same time, and the last remaining number is this number. If there are two remaining, then these two are the same, which is the result. On the basis of it, use the original array to traverse the last remaining number or two, and traverse the array to count the number of occurrences of the number to make the final judgment.

Use the elimination method to solve, one data is different from another data, then times=0 means it has been eliminated

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.size() == 0) return 0;

        int number = numbers[0];
        int times = 1;
        for(int i = 1; i < numbers.size(); i++)
        {
            if(times == 0)
            {
                number = numbers[i];
                times = 1;
                continue;
            }
            if(numbers[i] == number)
                times++;
            else times--;//两个数不同,则抵消
        }
        
        //后续还要再确认一下是否是这个数据
        int count = 0;
        for(int i = 0; i < numbers.size(); i++)
        {
            if(numbers[i] == number) count++;
        }

        return count > numbers.size()/2 ? number : 0;
    }
};

Guess you like

Origin blog.csdn.net/m0_61780496/article/details/130018559
Recommended