66. 构建乘积数组
代码:
动态规划
class Solution {
public int[] constructArr(int[] a) {
int len = a.length;
if(len == 0) return new int[0];
int[] dp = new int[a.length];
dp[0] = 1;
int tmp = 1;
//计算i左边的乘积
for(int i = 1; i < len; ++i){
dp[i] = dp[i-1]*a[i-1];
}
for(int i = len-2; i >= 0; --i){
//计算i右边的乘积
tmp *= a[i+1];
//将左右两边的乘积相乘
dp[i] *= tmp;
}
return dp;
}
}
60. n个骰子的点数
代码:
动态规划
dp[i][k]代表i个骰子总数为k时的概率。dp[i][k]=dp[i-1][k-1]*1/6+…+dp[i-1][k-6]*1/6。为防止溢出,从前向后计算。由于dp[i]的值只与dp[i-1]相关,故只需要两个一维数组即可。
class Solution {
public double[] dicesProbability(int n) {
double[] dp = new double[6];
//当n=1时,概率均为1/6
Arrays.fill(dp,1.0/6);
//计算骰子数量从2到n的结果
for(int i = 2; i <= n; ++i){
//点数取值范围为i~6i,共有5i+1个数
double[] tmp = new double[5*i+1];
//遍历n=i-1时dp数组的取值
for(int j = 0; j < dp.length; ++j){
//第i个骰子总共有6种取值
for(int k = 0; k < 6; ++k){
//n=i时,dp可以取得的点数为n=i-1时的点数加上第i个骰子的点数
tmp[j+k] += dp[j] * 1/6;
}
}
dp=tmp;
}
return dp;
}
}
58 - II. 左旋转字符串
代码:
截取子字符串
class Solution {
public String reverseLeftWords(String s, int n) {
String sub1 = s.substring(0, n);
String sub2 = s.substring(n);
return sub2+sub1;
}
}
若禁止使用substring方法
改进:
取余操作保证了先添加n后面的元素再添加n前的元素。
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder res = new StringBuilder();
for(int i = n; i < n+s.length(); ++i){
res.append(s.charAt(i%s.length()));
}
return res.toString();
}
}
47. 礼物的最大价值
代码:
动态规划
class Solution {
public int maxValue(int[][] grid) {
int[][] dp = new int[grid.length][grid[0].length];
dp[0][0] = grid[0][0];
for(int i = 1; i < dp.length; ++i){
dp[i][0] = grid[i][0] + dp[i-1][0];
}
for(int i = 1; i < dp[0].length; ++i){
dp[0][i] = grid[0][i] + dp[0][i-1];
}
for(int i = 1; i < dp.length; ++i){
for(int j = 1; j < dp[0].length; ++j){
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + grid[i][j];
}
}
return dp[dp.length-1][dp[0].length-1];
}
}
改进:
可以直接对原数组进行改变,节省空间。
class Solution {
public int maxValue(int[][] grid) {
for(int i = 1; i < grid.length; ++i){
grid[i][0] += grid[i-1][0];
}
for(int i = 1; i < grid[0].length; ++i){
grid[0][i] += grid[0][i-1];
}
for(int i = 1; i < grid.length; ++i){
for(int j = 1; j < grid[0].length; ++j){
grid[i][j] += Math.max(grid[i-1][j], grid[i][j-1]);
}
}
return grid[grid.length-1][grid[0].length-1];
}
}
21. 调整数组顺序使奇数位于偶数前面
代码:
双指针
class Solution {
public int[] exchange(int[] nums) {
int i = 0, j = nums.length-1;
while(i < j){
while(i<j && nums[i] % 2 == 1) i++;
while(i<j && nums[j] % 2 == 0) j--;
int temp = nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
return nums;
}
}
法二:
快慢指针,快指针指向奇数元素,慢指针指向可以存放的位置。
class Solution {
public int[] exchange(int[] nums) {
int fast = 0, slow = 0;
while(fast<nums.length){
if(nums[fast] % 2 == 1){
int temp = nums[slow];
nums[slow] = nums[fast];
nums[fast] = temp;
slow++;
}
fast++;
}
return nums;
}
}