動態規劃。 以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;
}
}
複製代碼