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

46 篇文章 0 订阅

问题:Next Greater Element I

难度:easy

说明:

题目给出数组 A 是数组 B 的一个子串,然后要求找到 A 里面元素,在 B 里面所在位置,然后从 B 里面那个位置开始,找到第一个比该元素值大的元素,然后返回所有比 A 大元素的集合。

题目连接:https://leetcode.com/problems/next-greater-element-i/

输入范围:

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

输入案例:

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.

我的代码:

简单,暴力的话就来个 三重循环,遍历 A 集合,然后找到 B 集合相等的元素,然后 再 从该位置开始遍历 B 集合,找到右边第一个元素即可。

不过可以加一个 map 做缓存,能够避免 A 重复元素。

我再将 B 所有元素都弄成 map,然后遍历 A 直接拿更快。

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;
    }
};

问题:Next Greater Element II

难度:medium

说明:

题目给出一个数组,然后数组是头尾相接,你需要把里面所有元素都找出右边第一个大的元素。

题目连接:https://leetcode.com/problems/next-greater-element-ii/

输入范围:

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

输入案例:

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.

我的代码:

暴力是在太好解了,但是这样子又会导致运行时间变慢,

暴力(压个行):

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;
    }
}

也可以弄个单调栈,这个比较中规中矩,O(m*n)时间复杂度

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

难度:medium

说明:

题目给出一个数字 N,然后把位数字数量相同,并且各个位数字组合成的 新 数字是最小的,刚好比 N 大的数字,如果不存在或者超过 int 就返回 -1。

题目连接:https://leetcode.com/problems/next-greater-element-iii/

输入范围:

  • 1 <= n <= 231 - 1

输入案例:

Example 1:
Input: n = 12
Output: 21

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

我的代码:

刚好比 N 大,然后又是最小的一个

1、先从尾部开始找 第一个 N[i - 1] < N[i];

2、把 N[i] ~ N[len] 里面 > N[i - 1] 并且是最小的数字和 N[i - 1] 对换;

3、最后把 N[i + 1] ~ N[len] 重新排序

C++和java只是比较顺序不同

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;
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值