[Leetcode学习-c++&java]Next Greater Element I ~ III

问题:Next Greater Element I

Difficulty: easy

Description:

The title gives that array A is a substring of array B, and then asks to find the element in A, the position in B, and then from that position in B, find the first element whose value is greater than the value of the element, and then return all the elements A collection of large elements.

Subject link: https://leetcode.com/problems/next-greater-element-i/

Input range:

  • All elements in nums1 and nums2 are unique.
  • The length of both nums1 and nums2 would not exceed 1000.

Enter the case:

Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]  // 注意 1 在 nums2 是第一个,右边比他大第一个是 3
Explanation:
    For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
    For number 1 in the first array, the next greater number for it in the second array is 3.
    For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4].
Output: [3,-1]
Explanation:
    For number 2 in the first array, the next greater number for it in the second array is 3.
    For number 4 in the first array, there is no next greater number for it in the second array, so output -1.

My code:

If it is simple and violent, it will be a triple loop, traverse the A set, and then find the equivalent element of the B set, and then traverse the B set from that position to find the first element on the right.

However, you can add a map as a cache to avoid duplicate elements in A.

I then make all the elements of B into a map, and then traverse A directly to make it faster.

Java:

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] greater = new int[nums1.length];
        HashMap<Integer, Integer> cache = new HashMap<Integer, Integer>();
        for(int j = 0;j < nums2.length;j ++) 
            for(int t = j + 1;t < nums2.length;t ++) 
                if(nums2[j] < nums2[t]) {
                    cache.put(nums2[j], nums2[t]);
                    break;
                }
        for(int i = 0;i < nums1.length;i ++) {
           if(cache.containsKey(nums1[i])) greater[i] = cache.get(nums1[i]);
           else greater[i] = -1;
        }
        return greater;
    }
}

C++:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        map<int, int> cache;
        vector<int> greater;
        for(int i = 0;i < nums2.size();i ++) 
            for(int j = i + 1;j < nums2.size();j ++) 
                if(nums2[j] > nums2[i]) {
                    cache[nums2[i]] = nums2[j];
                    break;
                }
        for(int i = 0;i < nums1.size();i ++)
            if(cache.count(nums1[i])) greater.push_back(cache[nums1[i]]);
            else greater.push_back(-1);
        return greater;
    }
};

Question: Next Greater Element II

Difficulty: medium

Description:

The title is given an array, and then the array is connected end to end. You need to find the first large element on the right side of all the elements in it.

Subject link: https://leetcode.com/problems/next-greater-element-ii/

Input range:

  • The length of given array won't exceed 10000.

Enter the case:

Input: [1,2,1]
Output: [2,-1,2]
Explanation: The first 1's next greater number is 2; 
The number 2 can't find next greater number; 
The second 1's next greater number needs to search circularly, which is also 2.

My code:

Violence is too easy to solve, but this will slow down the running time.

Violence (suppress a line):

Java:

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] greater = new int[nums.length];
        for(int i = 0, len = nums.length, j, t;i < len;greater[i] = j < len ? nums[t] : -1, i ++)
            for(j = 1, t = (i + j) % len;j < len && nums[t] <= nums[i];j ++, t = (i + j) % len);
        return greater;
    }
}

You can also make a monotonous stack, which is quite satisfactory, with O(m*n) time complexity

Java:

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int top = 0, len = nums.length, i;
        int[] greater = new int[len];
        if(nums.length == 0) return greater;
        int[][] mStack = new int[len][2];
        for(i = 1, mStack[top][0] = nums[0];i < len;i ++) {
            while(top >= 0 && nums[i] > mStack[top][0]) {
                greater[mStack[top][1]] = nums[i]; top --;
            }
            mStack[++ top][0] = nums[i];
            mStack[top][1] = i;
        }
        while(top >= 0) {
            for(i = 0;i < len;i ++) {
                while(top >= 0 && nums[i] > mStack[top][0]) {
                    greater[mStack[top][1]] = nums[i]; top --;
                }
            }
            greater[mStack[top --][1]] = -1;
        }
        return greater;
    }
}

C++:

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
		int len = nums.size(), top = 0, i;
		vector<int> greater(len);
		if (!len) return greater;
		int (*mStack)[2] = new int[len][2];
		for (i = 1, mStack[top][0] = nums[0], mStack[top][1] = 0; i < len; i++) {
			while (top >= 0 && nums[i] > mStack[top][0]) {
				greater[mStack[top][1]] = nums[i]; top--;
			}
			mStack[++top][0] = nums[i];
			mStack[top][1] = i;
		}
		for (i = 0; i < len; i++) {
			while (top >= 0 && nums[i] > mStack[top][0]) {
				greater[mStack[top][1]] = nums[i]; top--;
			}
		}
		while (top >= 0) greater[mStack[top--][1]] = -1;
		return greater;
	}
};

问题:Next Greater Element III

Difficulty: medium

Description:

The question gives a number N, and then the number of digits is the same, and the new number combined by each digit is the smallest, just a number larger than N. If it does not exist or exceeds int, it returns -1.

Title link: https://leetcode.com/problems/next-greater-element-iii/

Input range:

  • 1 <= n <= 231 - 1

Enter the case:

Example 1:
Input: n = 12
Output: 21

Example 2:
Input: n = 21
Output: -1

My code:

Just bigger than N, and then the smallest one

1. Find the first N[i-1] <N[i] from the tail;

2. Swap the smallest number in N[i] ~ N[len]> N[i-1] and N[i-1];

3. Finally, reorder N[i + 1] ~ N[len]

C++ and java just compare in different order

Java:

class Solution {
    public int nextGreaterElement(int n) {
        char[] chs = String.valueOf(n).toCharArray();
            int[] nums = new int[chs.length];
            for(int i = chs.length; i -- > 0;) nums[i] = chs[i] - '0';
            for(int i = nums.length; i -- > 1;) {
                if(nums[i - 1] < nums[i]) { // 先找出 下降的数字
                    int ti = i;
                    // 从 i 开始找出最小的 > nums[i - 1]的数
                    while(ti + 1 < nums.length && nums[i - 1] < nums[ti + 1]) ti ++;
                    // 然后置换 
                    nums[i - 1] ^= nums[ti];
                    nums[ti] ^= nums[i - 1];
                    nums[i - 1] ^= nums[ti];
                    // 最后重排序一遍
                    for(int j = i, end = chs.length - 1; j < end; j ++, end --) {
                        int tj = j;
                        while(tj + 1 <= end && nums[j] >= nums[tj + 1]) tj ++;
                        nums[tj] ^= nums[j];
                        nums[j] ^= nums[tj];
                        nums[tj] ^= nums[j];
                    }
                    // 转为数字输出
                    for(int j = nums.length;j -- > 0;) chs[j] = (char)(nums[j] + '0');
                    try { // 我决定用 try...catch 这个奇淫技巧
                        return Integer.valueOf(new String(chs));
                    } catch (Exception e) {
                        return -1;
                    }
                }
            }
            return -1;
    }
}

C++:

class Solution {
public:
	int nextGreaterElement(int n) {
		int index = 0, tens = 10, nums[32];
		long long res = 0;
		for (; n; n /= tens) 
			nums[index++] = n % tens;
		for (int i = 0; i < index - 1; i++) {
			if (nums[i] > nums[i + 1]) {
				int ti = i + 1, begin = 0;
				for (; ti - 1 >= 0 && nums[ti - 1] > nums[i + 1]; ti--);
				swap(nums[ti], nums[i + 1]);
				for (int j = i; j > begin; j--, begin ++) {
					int tj = j;
					while (tj - 1 >= begin && nums[j] >= nums[tj - 1]) tj--;
					swap(nums[tj], nums[j]);
				}
				for (int j = index; j -- > 0;) 
					if(res * tens <= INT_MAX) res = res * tens + nums[j];
					else return -1;
				return res;
			}
		}
		return - 1;
	}
};

 

Guess you like

Origin blog.csdn.net/qq_28033719/article/details/111604585