算法 --- 数组部分

问题描述:

有n(n<=10^8)个整数的无序数组 [1, 8, 6, 5, 3, 2, 9, 7],找出每个元素右边最近大于当前元素的数, 不存在则输出-1,要求时间复杂度O(N)
输入:
[1, 8, 6, 5, 3, 2, 9, 7]
输出:
[8, 9, 9, 9, 9, 9, -1, -1]

解题思路:

1>利用暴力解法,使用两层循环来实现的话时间复杂度为O(n^2)。

2>利用单调栈来实现,步骤如下:

   2-1>初始时,栈里放的是第一个元素的索引值0;

   2-2>循环遍历nums数组,

    如果栈不为空且当前遍历的元素nums[i]大于栈顶的元素值nums[stack.peek()],说明当前元素正好是栈顶元素右边第一个比它大的元素,将栈顶元素弹出,result[stack.pop()]=nums[i]。如果此时栈依然不为空的话,要进行栈的遍历,判断当前遍历元素nums[i]是否大于新的栈顶元素值nums[stack.peek()],若大于,则出栈。

    如果当前遍历的元素值nums[i]小于栈顶元素索引的值nums[stack.peek()],说明还未找到栈顶元素中右边第一个比它大的元素,直接将当前遍历的元素的索引入栈即可stack.push(i);

    重复上述步骤,直到遍历完所有元素,如果栈不为空,说明栈中保存的全是未找到右边第一个比它大的数组索引,我们依次将这些栈元素出栈,并赋值result[stack.pop()]=-1即可。
 

Java源码实现:

public void searchRightFirstMax(int[] nums) {
        int[] result = new int[nums.length];
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        int i = 1;
        for (; i < nums.length && !stack.isEmpty(); i++) {
            if (nums[i] > nums[stack.peek()]) {
                result[stack.pop()] = nums[i];
                while(!stack.isEmpty()) {
                    if (nums[i] > nums[stack.peek()]) {
                        result[stack.pop()] = nums[i];
                    }
                }
            }
            stack.push(i);
        }
        while(!stack.isEmpty()) {
            result[stack.pop()] = -1;
        }
        for (int j = 0; j < result.length;j++) {
            System.out.print(result[j] + ",");
        }
    }

问题描述:

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

解题思路:

利用快速排序的思路进行编写

Java源码实现:

public void searchNumsBySum(int[] nums,int sum) {
        int start = 0;
        int end = nums.length - 1;
        List<Integer> result = new ArrayList<>();
        while(start < end) {
            if (nums[start] + nums[end] == sum) {
               if (result.size() > 0) {
                   if (nums[start] * nums[end] < result.get(0) * result.get(1)) {
                       result.set(0,nums[start]);
                       result.set(1,nums[end]);
                   }
               } else {
                   result.add(nums[start]);
                   result.add(nums[end]);
               }
               end--;
            } else if (nums[start] + nums[end] > sum) {
                end--;
            } else if (nums[start] + nums[end] < sum) {
                start++;
            }
        }
        if (result.size() > 0) {
            System.out.println(result.get(0) + "," + result.get(1));
        } else {
            System.out.println("不存在符合条件的数据!");
        }
    }

问题描述:

两个有序数组合并成一个有序数组

Java源码实现(转):

public class MyClass {
    public static void main(String[] args) {
        int[] num1 = new int[]{1, 2, 4, 6, 7, 123, 411, 5334, 1414141, 1314141414};
        int[] num2 = new int[]{0, 2, 5, 7, 89, 113, 5623, 6353, 134134};
        //变量用于存储两个集合应该被比较的索引(存入新集合就加一)
        int a = 0;
        int b = 0;
        int[] num3 = new int[num1.length + num2.length];
        for (int i = 0; i < num3.length; i++) {
            if (a < num1.length && b < num2.length) {   //两数组都未遍历完,相互比较后加入
                if (num1[a] > num2[b]) {
                    num3[i] = num2[b];
                    b++;
                } else {
                    num3[i] = num1[a];
                    a++;
                }
            } else if (a < num1.length) {   //num2已经遍历完,无需比较,直接将剩余num1加入
                num3[i] = num1[a];
                a++;
            } else if (b < num2.length) {    //num1已经遍历完,无需比较,直接将剩余num2加入
                num3[i] = num2[b];
                b++;
            }
        }
        System.out.println("排序后:" + Arrays.toString(num3));
    }
}

问题描述:

一个前面升序后面降序的数组,找最大值。

Java源码实现:

public class Main {
 
	public static void main(String[] args) {
		int[] attr = { 1, 2, 3, 5, 9, 6, 4 };
		System.out.println(find(attr));
	}
 
	public static int find(int[] attr) {
		int s = 0;
		int e = attr.length;
		while (s <= e) {
			int m = (s + e) / 2;
			if (m == s || m == e - 1) {
				return m;
			}
			if (attr[m] >= attr[m - 1] && attr[m] >= attr[m + 1]) {
				return m;
			} else if (attr[m] < attr[m - 1]) {
				e = m - 1;
			} else if (attr[m] > attr[m - 1]) {
				s = m + 1;
			}
		}
		return -1;
	}
}

问题描述:

给一个数组和 target 值,找出长度最长的且和等于 target 的连续子数组的长度,时间复杂度要求O(n)

Java源码实现:

public class Main {
    public static void main(String[] args) {
        int[] nums = {1,3,4,5,1,1,1,1};
        int target = 5;
        System.out.println(maxLenthSubArray(nums,target));
    }
    public static int maxLenthSubArray(int[] nums, int target) {
        int ans = 0;
        int[] d = new int[nums.length];
        d[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            d[i] = d[i - 1] + nums[i];
        }
        int pre = 0;
        int last = 1;
        while (last < nums.length && pre < nums.length){
            if (d[last] - d[pre] == target){
                if (ans < last - pre)
                    ans = last - pre;
                last++;
                continue;
            }
            if (d[last] - d[pre] > target)
                pre++;
            if (d[last] - d[pre] < target)
                last++;
            // System.out.println(last + " " + pre);  // 看双指针的移动
        }
        return ans;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值