forked from floor07/DataStructuresAndAlgorithm-Demo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package chapter10.recollection; | ||
|
||
import java.util.Arrays; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
public class NumberCombo { | ||
|
||
|
||
|
||
private int n; // 被求组合数的自然数 | ||
private int r; // 要求组合数的自然数个数 | ||
private int[] a; // 解 | ||
|
||
public NumberCombo(int _n, int _r) { | ||
n = _n; | ||
r = _r; | ||
a = new int[_r + 1]; //解是从1开始对应的。 | ||
} | ||
|
||
|
||
public List<int[]> combOrderIndex() { | ||
|
||
List<int[]> selectIndexList = new LinkedList<int[]>(); | ||
|
||
combOrder(selectIndexList); | ||
|
||
return selectIndexList; | ||
} | ||
|
||
/** | ||
* 核心处理方法 | ||
* @param selectIndexList 存储结果 | ||
*/ | ||
private void combOrder(List<int[]> selectIndexList) { | ||
|
||
if(r==0){ | ||
return ; | ||
} | ||
if(r==1){ | ||
for (int i = 0; i<n; i++) { | ||
selectIndexList.add(new int[] { i }); | ||
} | ||
return; | ||
} | ||
int resultIndex=1; | ||
a[1]=1; | ||
while(a[1]<=(n-r+1)){//根据第一位进行裁剪,第一位取值为1<a[1]<n-r+1 列入5个数选3个 第一位最大为5-3+1=3 | ||
if(resultIndex<r){ | ||
if(a[resultIndex]<=n-r+resultIndex){ | ||
a[resultIndex+1] = a[resultIndex]+1; | ||
resultIndex++; | ||
}else{// 已经超过每一位的最大值 n-r+resultIndex,进行回溯 | ||
resultIndex--; | ||
a[resultIndex]=a[resultIndex]+1; | ||
} | ||
}else if(resultIndex==r){ | ||
int[] selectIndex = new int[r]; | ||
selectIndexList.add(selectIndex); | ||
for (int j = 1; j <= r; j++) {//存储结果 | ||
selectIndex[j - 1] = a[j]-1; | ||
} | ||
if (a[resultIndex]==n) { // 若当前搜索结果为1,表示本次搜素完成,进行回溯 此时条件相当为 ri+a[ri]==r+1 因为ri=r所以简化啦 | ||
resultIndex--; | ||
a[resultIndex] = a[resultIndex]+1; // 回溯 | ||
} else { | ||
a[resultIndex] = a[resultIndex]+1; // 搜索到下一个数 | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
/** | ||
* @param args | ||
*/ | ||
public static void main(String[] args) { | ||
// 测试例子 | ||
NumberCombo nc = new NumberCombo(5, 3); | ||
List<int[]> indexList2 = nc.combOrderIndex(); | ||
for(int i=0;i<indexList2.size();i++){ | ||
System.out.println(Arrays.toString(indexList2.get(i))); | ||
} | ||
System.out.println(indexList2.size()+"====================================="+indexList2.size()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package chapter10.recollection; | ||
|
||
import java.util.Arrays; | ||
import java.util.Comparator; | ||
import java.util.PriorityQueue; | ||
|
||
/** | ||
* 回溯算法解 高速公路问题 设给定N个点P1,P2,.......,PN,它们位于X轴上。Xi是Pi点的X坐标。<br/> | ||
* 进一步假设X1=0以及这些点从左到右给出。着N个点确定,在每一对,点间的N(N-1)/2个,<br/> | ||
* 形如|Xi - Xj|(i !=j)的距离。收费公路重建问题就是由这些距离重构一个点集。<br/> | ||
* | ||
* @author wenl | ||
*/ | ||
public class RebulidRoad { | ||
|
||
/** | ||
* @param x | ||
* 结果点集合 | ||
* @param distSet | ||
* 边的优先队列,注意队列从大到小 | ||
* @param n | ||
* 根据边集大小计算出来的 预计点个数, n(n-1)/2=distSet.size(); | ||
* @return | ||
*/ | ||
public static boolean turnpike(int[] x, PriorityQueue<Integer> distSet, int n) { | ||
// 倒序排列边集合 | ||
x[1] = 0; | ||
x[n] = distSet.poll(); | ||
x[n - 1] = distSet.poll(); | ||
if (distSet.contains(x[n] - x[n - 1])) { | ||
distSet.remove(new Integer(x[n] - x[n - 1])); | ||
return place(x, distSet, n, 2, n - 2); | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* 重建高速公路-回溯算法核心 | ||
* @param x 结果集合 | ||
* @param distSet 剩余边集合 从大到小构建的堆 | ||
* @param n 预计包含的点集合 | ||
* @param left 本次尝试的左边界 | ||
* @param right 本次尝试的右边开始点 | ||
*/ | ||
private static boolean place(int[] x, PriorityQueue<Integer> distSet, int n, int left, int right) { | ||
int dmax = 0; | ||
boolean found = false; | ||
if (distSet.isEmpty()) { | ||
return true; | ||
} | ||
dmax = distSet.peek(); | ||
// 尝试x[right]为 dmax | ||
if (CheckIfRight(x, distSet, n, left, right, dmax)) { | ||
x[right] = dmax; | ||
for (int j = 1; j < left; j++) { | ||
distSet.remove(new Integer(Math.abs(x[j] - x[right]))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
distSet.remove(new Integer(Math.abs(x[j] - x[right]))); | ||
} | ||
found = place(x, distSet, n, left, right - 1); | ||
if (!found) { | ||
for (int j = 1; j < left; j++) { | ||
distSet.add(new Integer(Math.abs(x[j] - x[right]))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
distSet.add(new Integer(Math.abs(x[j] - x[right]))); | ||
} | ||
} | ||
} | ||
// x[left]=x[n]-dmax | ||
if (!found && CheckIfleft(x, distSet, n, left, right, dmax)) { | ||
x[left] = x[n] - dmax; | ||
for (int j = 1; j < left; j++) { | ||
distSet.remove(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
distSet.remove(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
found = place(x, distSet, n, left + 1, right); | ||
if (!found) { | ||
for (int j = 1; j < left; j++) { | ||
distSet.add(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
distSet.add(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
} | ||
} | ||
return found; | ||
} | ||
|
||
private static boolean CheckIfleft(int[] x, PriorityQueue<Integer> distSet, int n, int left, int right, int dmax) { | ||
boolean flagL = true; | ||
for (int j = 1; j < left; j++) { | ||
flagL=flagL&&distSet.contains(Math.abs(x[n] - x[j] - dmax)); | ||
if(!flagL){ | ||
break; | ||
} | ||
} | ||
if (flagL) { | ||
for (int j = 1; j < left; j++) { | ||
distSet.remove(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
flagL=flagL&&distSet.contains(Math.abs(x[n] - x[j] - dmax)); | ||
if(!flagL){ | ||
break; | ||
} | ||
} | ||
for (int j = 1; j < left; j++) { | ||
distSet.add(new Integer(Math.abs(x[n] - dmax - x[j]))); | ||
} | ||
} | ||
return flagL; | ||
} | ||
|
||
private static boolean CheckIfRight(int[] x, PriorityQueue<Integer> distSet, int n, int left, int right, int dmax) { | ||
boolean flagR = true; | ||
for (int j = 1; j < left; j++) { | ||
flagR=flagR&&distSet.contains(Math.abs(x[j] - dmax)); | ||
if(!flagR){ | ||
break; | ||
} | ||
} | ||
if (flagR) { | ||
for (int j = 1; j < left; j++) { | ||
distSet.remove(new Integer(Math.abs(x[j] - dmax))); | ||
} | ||
for (int j = right + 1; j <= n; j++) { | ||
flagR=flagR&&distSet.contains(Math.abs(x[j] - dmax)); | ||
if(!flagR){ | ||
break; | ||
} | ||
} | ||
for (int j = 1; j < left; j++) { | ||
distSet.add(new Integer(Math.abs(x[j] - dmax))); | ||
} | ||
} | ||
|
||
return flagR; | ||
} | ||
|
||
public static void main(String[] args) { | ||
int[] x = new int[7]; | ||
PriorityQueue<Integer> distSet = new PriorityQueue<Integer>(15, new Comparator<Integer>() { | ||
@Override | ||
public int compare(Integer o1, Integer o2) { | ||
return o2.compareTo(o1); | ||
} | ||
}); | ||
distSet.add(1); | ||
distSet.add(2); | ||
distSet.add(2); | ||
distSet.add(2); | ||
distSet.add(3); | ||
distSet.add(3); | ||
distSet.add(3); | ||
distSet.add(4); | ||
distSet.add(5); | ||
distSet.add(5); | ||
distSet.add(5); | ||
distSet.add(6); | ||
distSet.add(7); | ||
distSet.add(8); | ||
distSet.add(10); | ||
System.out.println(distSet); | ||
boolean isTrue = turnpike(x, distSet, 6); | ||
|
||
System.out.println(isTrue); | ||
System.out.println(Arrays.toString(x)); | ||
System.out.println(distSet); | ||
|
||
} | ||
} |