动态规划。 以a字符为例,令 dp[i][j] 表示将从第 i 个 a 字符(包含)到第 j 个 a 字符(包含)之间的全部 a 字符移动到一块儿的交换次数,咱们能够知道将全部的字符往中间移动的代价是最小的。 同时,假设从第 i + 1 个 a 字符到第 j - 1 个 a 字符之间的全部字符 a 都已经移动到一块儿了,不管它们的位置如何,则只需把 i 位置和 j 位置的 a 字符忘中间移动,便可获得把第 i 个 a 字符(包含)到第 之间的全部 到一块儿的最小操做次数,且该步骤的操做次数必定为第 j 个 a 字符的下标减去第 i 个 a 字符的下标加一再减第 i + 1 个 a 字符到第 j - 1 个 a 字符之间的全部字符 a 的数量。
package exam1.q4;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n, x;
n = sc.nextInt();
x = sc.nextInt();
long[] a = new long[n];
long min = Long.MAX_VALUE;
int startx = -1;
for(int i = 0; i < n; i++) {
a[i] = sc.nextInt();
if(a[i] < min) {
min = a[i];
}
}
x--;
sc.close();
for(int i = 0; i < n; i++) {
if(a[i] == min) {
int tmp = x - i;
if(tmp < 0)
tmp += n;
boolean f = true;
for(int j = 1; j <= tmp; j++) {
if(a[(i + j) % n] < min + 1){
f = false;
break;
}
}
if(f){
startx = i;
break;
}
}
}
long remain = 0;
if(x < startx)
remain = x + n - startx;
else
remain = x - startx;
long round = min;
for(int i = 0; i < n; i++)
a[i] -= round;
for(int i = 1; i <= remain; i++)
a[(startx + i) % n] -= 1;
a[startx] = round * n + remain;
for(int i = 0; i < n; i++)
System.out.print(a[i] + " ");
System.out.println();
}
}
复制代码
第五题:跳房子
题目
存在 n + 1 个房间,每一个房间依次为房间 1 2 3…i,每一个房间都存在一个传送门,i房间的传送门能够把人传送到房间 pi(1<=pi<=i),如今路人甲从房间 1 开始出发(当前房间 1 即第一次访问),每次移动他有两种移动策略: A. 若是访问过当前房间 i 偶数次,那么下一次移动到房间i+1; B. 若是访问过当前房间 i 奇数次,那么移动到房间pi; 如今路人甲想知道移动到房间n+1一共须要多少次移动; 输入描述: 第一行包括一个数字 n(30%数据1 <= n <= 100,100%数据 1 <= n <= 1000),表示房间的数量,接下来一行存在 n 个数字 pi(1 <= pi <= i), pi 表示从房间 i 能够传送到房间 pi。 输出描述: 输出一行数字,表示最终移动的次数,最终结果须要对1000000007 (10e9 + 7) 取模。
package tideTheRoom;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
private static class Point implements Cloneable {
long x;
long y;
long a;
long b;
int cnt;
public Point(long x, long y, long a, long b, int cnt) {
super();
this.x = x;
this.y = y;
this.a = a;
this.b = b;
this.cnt = cnt;
}
public void rotate() {
if (this.cnt == 3)
return;
long tx = a - y + b;
long ty = x - a + b;
this.x = tx;
this.y = ty;
this.cnt++;
}
@Override
public Point clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
}
return (Point) o;
}
}
private static boolean check(Point[] p) {
long[] dist = new long[6];
int cnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = i + 1; j < 4; j++) {
dist[cnt++] = (p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y);
}
}
Arrays.sort(dist);
if (dist[0] == dist[1] && dist[0] == dist[2] && dist[0] == dist[3] && dist[4] == dist[5]
&& !(dist[0] == dist[4]))
returntrue;
returnfalse;
}
private static int bfs(Point[] p) {
boolean[][][][] visited = new boolean[4][4][4][4];
LinkedList<Point[]> que = new LinkedList<>();
que.addLast(p);
visited[0][0][0][0] = true;
if (check(p))
return 0;
while (!que.isEmpty()) {
Point[] f = que.pollFirst();
for (int i = 0; i < 4; i++) {
Point[] tmp = new Point[4];
for (int j = 0; j < 4; j++) {
tmp[j] = f[j].clone();
}
tmp[i].rotate();
if (visited[tmp[0].cnt][tmp[1].cnt][tmp[2].cnt][tmp[3].cnt])
continue;
if (check(tmp)) {
return tmp[0].cnt + tmp[1].cnt + tmp[2].cnt + tmp[3].cnt;
}
que.addLast(tmp);
visited[tmp[0].cnt][tmp[1].cnt][tmp[2].cnt][tmp[3].cnt] = true;
}
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while ((n--) != 0) {
Point[] p = new Point[4];
for (int i = 0; i < 4; i++) {
long x = sc.nextLong();
long y = sc.nextLong();
long a = sc.nextLong();
long b = sc.nextLong();
p[i] = new Point(x, y, a, b, 0);
}
System.out.println(bfs(p));
}
sc.close();
}
}
复制代码
第二题:小易的字典
题目:
小易在学校中学习了关于字符串的理论, 因而他基于此完成了一个字典的项目。 小易的这个字典很奇特, 字典内的每一个单词都包含n个’a’和m个’z’, 而且全部单词按照字典序排列。 小易如今但愿你能帮他找出第k个单词是什么。 输入描述: 输入包括一行三个整数n, m, k(1 <= n, m <= 100, 1 <= k <= 109), 以空格分割。 输出描述: 出第k个字典中的字符串,若是无解,输出-1。
package dictionary;
import java.util.Scanner;
import static java.lang.Math.log;
import java.math.BigInteger;
import static java.lang.Math.exp;
public class Main {
public static long comb(int m, int n, long target) {// 计算假设a肯定以后,a以后的部分排列组合数
if (m == 0 || n == 0)
return 1;
long sum = m + n;
long k = 1;
n = Math.min(m, n);// C(m+n) n=C(m+n) m 取最小便可
for (int i = 0; i < n; i++) {
k *= sum - i;
k /= (i + 1);
if (k > target)// 防止大数。若是k>target 则只进行list.add("a")和m--//a的个数减1。
// 没有target -= k;所以不影响
break;
}
return k;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
int tn = n, tm = m;
StringBuilder sb = new StringBuilder();
while (tn > 0 && tm > 0) {
long c = comb(tn - 1, tm, k);
// System.out.println(c);
if (k <= c) {
sb.append('a');
tn--;
} else {
sb.append('z');
k -= c;
tm--;
}
}
if (k != 1)
System.out.println(-1);
else {
while (tn > 0) {
sb.append('a');
tn--;
}
while (tm > 0) {
sb.append('z');
tm--;
}
System.out.println(sb.toString());
}
sc.close();
}
}
复制代码
刷了一些LeetCode题
第一题:LeetCode 42 Trapping Rain Water 和 LeetCode 407 Trapping Rain Water II
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
Example:
Input:[0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
题意
给 n 个柱子做为隔板,问柱子之间最多能存多少水
思路
根据木桶效应,能装多少水是由左右两边最高的柱子中的最矮柱子来决定的。
我一开始的作法是用两个数组 maxHeightLeft 和 maxHeightRight 分别记录位置 i 左边的最高柱子和右边的最高柱子。而后遍历从 1 到 n – 2,
import java.lang.Math;
public class Solution {
public int trap(int[] height) {
int len = height.length;
int[] maxHeightLeft = new int[len];
int[] maxHeightRight = new int[len];
for(int i = 1; i < len; i ++){
if(height[i - 1] > maxHeightLeft[i - 1])
maxHeightLeft[i] = height[i - 1];
else
maxHeightLeft[i] = maxHeightLeft[i - 1];
}
for(int i = len - 2; i >= 0; i --) {
if(height[i + 1] > maxHeightRight[i + 1])
maxHeightRight[i] = height[i + 1];
else
maxHeightRight[i] = maxHeightRight[i + 1];
}
int sum = 0;
for(int i = 1; i < len - 1; i ++){
int shortEdge = Math.min(maxHeightLeft[i], maxHeightRight[i]);
if(shortEdge > height[i])
sum += shortEdge - height[i];
}
return sum;
}
}
复制代码
LeetCode 407 Trapping Rain Water II
Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.
Note: Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.
Example: Given the following 3×6 height map: [ [1,4,3,1,3,2], [3,2,1,3,2,4], [2,3,3,2,3,1] ] Return 4.
The above image represents the elevation map
[[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]before the rain.
After the rain, water is trapped between the blocks. The total volume of water trapped is 4.
import java.util.Comparator;
import java.util.PriorityQueue;
import static java.lang.Math.max;
public class Solution1 {
private final static int[][] steps = new int[][] { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
private class Point {
int x;
int y;
int height;
public Point(int x, int y, int height) {
super();
this.x = x;
this.y = y;
this.height = height;
}
}
private class Comparator1 implements Comparator<Point> {
@Override
public int compare(Point o1, Point o2) {
if (o1.height > o2.height)
return 1;
return -1;
}
}
public int trapRainWater(int[][] heightMap) {
int ans = 0;
int lenx = heightMap.length;
if (lenx < 3)
return 0;
int leny = heightMap[0].length;
if (leny < 3)
return 0;
boolean[][] visited = new boolean[lenx][leny];
PriorityQueue<Point> que = new PriorityQueue<>(new Comparator1());
for (int i = 0; i < lenx; i++) {
que.add(new Point(i, 0, heightMap[i][0]));
visited[i][0] = true;
que.add(new Point(i, leny - 1, heightMap[i][leny - 1]));
visited[i][leny - 1] = true;
}
for (int i = 1; i < leny - 1; i++) {
que.add(new Point(0, i, heightMap[0][i]));
visited[0][i] = true;
que.add(new Point(lenx - 1, i, heightMap[lenx - 1][i]));
visited[lenx - 1][i] = true;
}
int maxHeight = -1;
while (!que.isEmpty()) {
Point cur = que.poll();
maxHeight = max(maxHeight, cur.height);
for (int i = 0; i < 4; i++) {
int nextX = cur.x + steps[i][0];
int nextY = cur.y + steps[i][1];
if (nextX >= 0 && nextX < lenx && nextY >= 0 && nextY < leny && !visited[nextX][nextY]) {
//System.out.println(nextX + " " + " " + nextY + " " + maxHeight + " " + heightMap[nextX][nextY]);
if (heightMap[nextX][nextY] < maxHeight) {
ans += maxHeight - heightMap[nextX][nextY];
}
visited[nextX][nextY] = true;
que.add(new Point(nextX, nextY, heightMap[nextX][nextY]));
}
}
}
return ans;
}
}
复制代码
第二题:leetcode 207 Course Schedule
题目
There are a total of n courses you have to take, labeled from 0 to n-1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair:[0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
Input: 2, [[1,0]] Output: true Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]] Output: false Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. You may assume that there are no duplicate edges in the input prerequisites.
思路
明显的拓扑排序,复习一下,顺便复习了一下图的链式前向星表示法
代码
package leetcode_207_course_schedule;
import java.util.HashSet;
import java.util.Stack;
public class Solution {
private class Edge {
int next;
int to;
public Edge(int next, int to) {
super();
this.next = next;
this.to = to;
}
};
int[] head;
Edge[] edges;
int cntE;
public void add(int u, int v) {
Edge e = new Edge(head[u], v);
edges[++cntE] = e;
head[u] = cntE; // 第一条边为当前边
}
public boolean canFinish(int numCourses, int[][] prerequisites) {
Stack<Integer> stack = new Stack<>();
int len = prerequisites.length;
HashSet<Integer> set = new HashSet<>();
int[] indegree = new int[numCourses];
head = new int[numCourses];
edges = new Edge[len + 1];
for (int i = 0; i < len; i++) {
indegree[prerequisites[i][1]]++;
add(prerequisites[i][0], prerequisites[i][1]);
}
for (int i = 0; i < numCourses; i++) {
set.add(i);
}
for (int i = 0; i < numCourses; i++) {
if (indegree[i] == 0)
stack.add(i);
}
while (!stack.empty()) {
int cur = stack.pop();
set.remove(cur);
for (int i = head[cur]; i != 0; i = edges[i].next) {
indegree[edges[i].to]--;
if (indegree[edges[i].to] == 0)
stack.push(edges[i].to);
}
}
if (set.size() == 0)
returntrue;
elsereturnfalse;
}
}
复制代码
第三题:LeetCode 871 Minimum Number of Refueling Stops
A car travels from a starting position to a destination which is target miles east of the starting position.
Along the way, there are gas stations. Each station[i] represents a gas station that is station[i][0] miles east of the starting position, and has station[i][1] liters of gas.
The car starts with an infinite tank of gas, which initially has startFuel liters of fuel in it. It uses 1 liter of gas per 1 mile that it drives.
When the car reaches a gas station, it may stop and refuel, transferring all the gas from the station into the car.
What is the least number of refueling stops the car must make in order to reach its destination? If it cannot reach the destination, return -1.
Note that if the car reaches a gas station with 0 fuel left, the car can still refuel there. If the car reaches the destination with 0 fuel left, it is still considered to have arrived.
Example 1:
Input: target = 1, startFuel = 1, stations = [] Output: 0 Explanation: We can reach the target without refueling.
Example 2:
Input: target = 100, startFuel = 1, stations = [[10,100]] Output: -1 Explanation: We can’t reach the target (or even the first gas station).
Example 3:
Input: target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]] Output: 2 Explanation: We start with 10 liters of fuel. We drive to position 10, expending 10 liters of fuel. We refuel from 0 liters to 60 liters of gas. Then, we drive from position 10 to position 60 (expending 50 liters of fuel), and refuel from 10 liters to 50 liters of gas. We then drive to and reach the target. We made 2 refueling stops along the way, so we return 2.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
public class Solution {
public class GasStation {
public int pos;
public int gas;
public GasStation(int pos, int gas) {
super();
this.pos = pos;
this.gas = gas;
}
}
class GasStationComparator1 implements Comparator<GasStation> {
@Override
public int compare(GasStation o1, GasStation o2) {
return o1.pos - o2.pos;
}
}
class GasStationComparator2 implements Comparator<GasStation> {
@Override
public int compare(GasStation o1, GasStation o2) {
return o2.gas - o1.gas;
}
}
public int minRefuelStops(int target, int startFuel, int[][] stations) {
int num_GS = stations.length;
List<GasStation> list = new ArrayList<>();
for (int[] gs : stations) {
list.add(new GasStation(gs[0], gs[1]));
}
list.add(new GasStation(target, 0));
list.sort(new GasStationComparator1());
int gas = startFuel;
PriorityQueue<GasStation> heap = new PriorityQueue<>(new GasStationComparator2());
int cnt = 0;
for (int i = 0; i < num_GS + 1; i++) {
GasStation gs = list.get(i);
if (gs.pos > gas) {
while (gs.pos > gas && !heap.isEmpty()) {
//System.out.println(heap.peek().pos + " " + heap.peek().gas);
gas += heap.poll().gas;
cnt++;
}
if (gs.pos > gas && heap.isEmpty()) {
return -1;
}
}
heap.add(gs);
}
return cnt;
}
}
复制代码