问题描述:
有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;
}
}