赞
踩
第一反应是创建一个额外数组,把后k位数组拿走放到前面来
class Solution{
public void rotate(int[] nums, int k){
//新建数组储存k位,进行移动
int n = nums.length;
k %= n;
int[] temp = new int[k];
System.arraycopy(nums, n - k, temp, 0, k);
for (int i = n-k-1; i >= 0; i--) nums[i+k] = nums[i];
System.arraycopy(temp, 0, nums, 0, k);
}
}
看了题解才发现另一个写法是环状替换,将每个数字向右移动k位,从而达到整个移动的效果
//图片源于官方题解
将第i位赋值给(i+k)%n位,并将(i+k)%n位赋值给((i+k)+k)%n位……,重复上述的操作直到赋值位回到第i位,若遍历的数字数量达到了n个,则代表遍历结束,反之则让i+1,继续遍历
先执行判断count数量操作,再执行start++操作,否则当nums.length为1时会出现数组越界问题
class Solution { public void rotate(int[] nums, int k) { //环状替换 int n = nums.length; int count = 0, start = 0, temp = nums[start], i, t; //temp储存被替换的数, t储存交换的数, i储存当前位置, count储存交换的次数, start储存起始位置 k %= n; i = start; while (count < n) { i = (i + k) % n; //交换temp和nums[(start+k)%n] t = nums[i]; nums[i] = temp; temp = t; count++; if (count == n) break; //判断是否回到原点,判断是否已经交换了n个数 if (i == start) { start++; i = start; temp = nums[start]; } } } }
简单的题目,设置minn,maxn,ans三个变量,如果有更低的价格则更新ans和minn,如果有更高的价格则更新maxn和ans
class Solution { public int maxProfit(int[] prices) { int maxn, minn, ans = 0; maxn = minn = prices[0]; for (int i = 1; i < prices.length; i++){ if (prices[i] < minn) { ans = Math.max(ans, maxn - minn); minn = maxn = prices[i]; } if (prices[i] > maxn) { maxn = prices[i]; ans = Math.max(ans, maxn - minn); } } return ans; } }
如果价格起伏很大,那么一直持有划算还是购买并买入划算呢? 这里假设操作为买、卖、空三种操作代表买入、卖出和不操作
如价格波动为1536,那么买卖买卖的利润为7,买空空卖的利润为5
易观察到:只要前一天的价格比后一天的高,那么先卖出再买入的利润一定高于持有不卖的利润
那么我们的购买策略应该是这样的
class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
for (int i = 0; i < prices.length - 1; i++)
if (prices[i+1] > prices[i]) profit += prices[i+1] - prices[i];
return profit;
}
}
简单的动态规划问题,建立一个长度为nums.length的boolean数组,除了0之外其他的值都为false
从0开始遍历,能到达的位置设为true
class Solution {
public boolean canJump(int[] nums) {
boolean judge[] = new boolean[nums.length];
judge[0] = true;
for (int i = 0; i < nums.length; i++)
if (judge[i])
for (int j = 1; j <= nums[i]; j++)
if (i + j < nums.length) judge[i + j] = true;
return judge[nums.length - 1];
}
}
然后发现运行时间过于长了,代码的时间复杂度是 O ( n 2 ) O(n^2) O(n2) 其中 n 是数组 nums 的长度。这是因为使用了两个嵌套的循环。外层循环遍历数组中的每个元素,内层循环根据当前位置能够跳跃的步数,更新布尔数组 judge。
可以只用一个变量来表示可以到达的长度,这样也能够代表跳跃的长度
class Solution {
public boolean canJump(int[] nums) {
int k = 0;
for (int i = 0; i < nums.length; i++){
if (i > k) return false;
k = Math.max(k, i + nums[i]);
}
return true;
}
}
怪不得刚刚控制不住自己建了一个boolean数组,原来是写过这道题
简单的动态规划问题,建立一个长度为nums.length的数组
从0开始遍历,能到达的位置更新最小跳跃数为当前位置+1
class Solution {
public int jump(int[] nums) {
int minn[] = new int[nums.length];
minn[0] = 1;//等等结果再减一,为了防止0的情况
for (int i = 0; i < nums.length; i++) {
if (minn[i]==0 || nums[i]==0) continue;
for (int j = 1; j <= nums[i]; j++) {
if (i+j >= nums.length) break;
if (minn[i+j] == 0) minn[i+j] = minn[i] + 1;
else minn[i+j] = Math.min(minn[i+j], minn[i] + 1);
}
}
return minn[nums.length-1]-1;
}
}
然后发现运行时间过于长了,看了题解才知道可以在一次循环中解决,其思路是:
class Solution {
public int jump(int[] nums) {
int curDis = 0,jump = 0, maxDis = 0;
for (int i = 0; i < nums.length - 1; i++){//最后一个元素不用跳
maxDis = Math.max(maxDis, i + nums[i]);
if (i == curDis) {
jump++;
curDis = maxDis;
}
}
return jump;
}
}
思路是排序后二分查找
class Solution { public int hIndex(int[] citations) { //排序citations int n = citations.length; Arrays.sort(citations); //二分查找 int l = 0, r = n - 1, mid; while (l <= r){ mid = (l+r) / 2; if (citations[mid]==n-mid) return n-mid; else if (citations[mid]>n-mid) r = mid - 1; else l = mid + 1; } return n-l; } }
上面的复杂度是 O ( n l o g ( n ) ) O(nlog(n)) O<
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。