本人Java入门小白,最近在看数据结构与算法分析--Java语言描述这本书,发现书本后面的习题真的很难。费了九牛二虎之力也只能解决一部分,因此决定记录一下,以供后期继续学习。文章中的代码全部为自己手动敲得,当然也有部分是参考网上大神的,欢迎各位大神指导。
编写一个程序解决选择问题。
本文主要采用两种方法。
第一种是通过某种排序算法(例如,冒泡排序)以递减的顺序将数组排序,然后返回第k个元素即可。
第二种是先把前k个元素读入数组并(以递减的顺序)对其进行排序。接着将剩下的元素再逐个读入。当新元素被读到时,如果它小于数组中的第k个元素则忽略,否则就将其放到数组中正确的位置上,同时将数组中的一个元素挤出数组。当算法结束时,位于第k个位置上的元素即为想要的答案。
第一种方法:
/**
* 获取一组数中的第k个最大的数
*
* @param arr
* @param k
* @return
*/
private static int getKthMaxNum1(int[] arr,int k){
sortArrayByDesc(arr);
return arr[k-1];
}
/**
* 冒泡排序(递减)
*
* @param arr
*/
private static void sortArrayByDesc(int[] arr){
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
if(arr[j] < arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
第二种方法:
/**
* 获取一组数中的第k个最大的数
*
* @param arr
* @param k
* @return
*/
private static int getKthMaxNum2(int[] arr,int k){
// 将前k个元素读入数组并降序排序
int[] newArr = Arrays.copyOf(arr, k);
sortArrayByDesc(newArr);
// 将剩下的元素与数组中的元素进行比较,如果小于数组中的第k个元素则忽略;
// 反之将其放到数组中正确的位置上,同时将数组中的一个元素挤出数组
updateKthOfArray(arr, k, newArr);
return newArr[k-1];
}
/**
* 更新数组
*
* @param arr
* @param k
* @param newArr
*/
private static void updateKthOfArray(int[] arr, int k, int[] newArr) {
for(int i = k; i < arr.length; i++){
// 大于数组中的第k个元素,将其放到数组中合适的位置
for(int j = 0; j < k - 1; j++){
if(arr[i] > newArr[j]){
newArr[j] = arr[i];
// 将newArr中j之后的所有元素都赋值为其本身前一位的元素的值
for(int m = k - 1; m > j; m--){
newArr[m] = newArr[m-1];
}
}
break;
}
}
}
方法二也可以换一种思路。
/**
* 获取一组数中的第k个最大的数
*
* @param arr
* @param k
* @return
*/
private static int getKthMaxNum2(int[] arr,int k){
// 将前k个元素读入数组并降序排序
int[] newArr = Arrays.copyOf(arr, k);
sortArrayByDesc(newArr);
// 将剩下的元素与数组中的第k个元素进行比较,如果小于则忽略;
// 反之,则进行替换并重新对数组进行降序排序。
for(int i = k; i < arr.length; i++){
if(arr[k] > newArr[k-1]){
newArr[k-1] = arr[k];
sortArrayByDesc(newArr);
}
}
return newArr[k-1];
}
问题拓展:如何向有序数组中添加新的元素?
/**
* 数组添加新元素
*
* @param arr
* @param n
*/
public static void insertElement(int[] arr,int n){
int[] newArr = new int[arr.length + 1];
for(int i = 0; i < arr.length; i++){
if(n < arr[i]){
newArr[i] = n;
for(i = i + 1; i < newArr.length; i++){
newArr[i] = arr[i-1];
}
}else{
newArr[i] = arr[i];
}
}
}
编写一个程序求解字谜游戏问题。
public class Puzzle_Game {
static final char[][] letters = new char[][]{
{'t', 'h', 'i', 's'},
{'w', 'a', 't', 's'},
{'o', 'a', 'h', 'g'},
{'f', 'g', 'd', 't'}
};
static String[] dic = {"this", "two", "fat", "that"};
static int minLenth = letters.length; //最小长度
static List list = new ArrayList<>();
public static void main(String[] args){
//1.找出最小长度
for (String string : dic) {
if(string.length() < minLenth)
minLenth = string.length();
}
//2.枚举字谜数组
getAllWords(minLenth);
//3.检索是否存在在字谜中
Set list2 = new TreeSet<>();
for (String str : list) {
for(int i = 0; i < dic.length; i++){
if(str.indexOf(dic[i]) != -1)
list2.add(dic[i]);
}
}
//4.打印单词
Iterator it = list2.iterator();
while (it.hasNext()){
String next = it.next();
System.out.print(next + ",");
}
}
/**
* 枚举字谜数组
*
* @param minLength
*/
public static void getAllWords(int minLength){
for(int i = 0; i < letters.length; i++){
//横向和纵向
char[] dir1 = new char[letters[i].length];
char[] dir2 = new char[letters[i].length];
for(int j = 0; j < letters[i].length; j++){
dir1[j] = letters[i][j]; //横向
dir2[j] = letters[j][i]; //纵向
}
list.add(String.valueOf(dir1));
list.add(String.valueOf(dir2));
//斜对角
if(i >= minLength - 1){
char[] dir3 = new char[i + 1]; //左上
char[] dir4 = new char[i + 1]; //左下
char[] dir5 = new char[i + 1]; //右上
char[] dir6 = new char[i + 1]; //右下
int k = 0, l = i, t = letters.length - 1;
while(l >= 0){
dir3[k] = letters[k][l];
dir4[k] = letters[t][l];
dir5[k] = letters[l][t];
dir6[k] = letters[letters.length - l - 1][t];
k++;
l--;
t--;
}
charReverse(dir3);
charReverse(dir4);
charReverse(dir5);
charReverse(dir6);
}
}
}
/**
* 字符反转
*
* @param c
*/
public static void charReverse(char[] c){
char[] c2 = new char[c.length];
int j = 0;
for(int i = c.length - 1; i >= 0; i--, j++){
c2[j] = c[i];
}
list.add(String.valueOf(c2));
list.add(String.valueOf(c));
}
}
只使用处理I/O的printDigit方法,编写一种方法以输出任意double型量(可以是负的)。
/**
* 只使用处理IO的printDigit方法,编写一种方法以输出任意double型量(可以是负的)。
*
* @param num
*/
public static void printNum(double num) {
if (num < 0) {
num = -num;
System.out.print("-");
}
//整数部分
int integral = (int) num;
printOut(integral);
//小数部分
double fraction = num - integral;
if(fraction != 0){
System.out.print(".");
}
printDouble(fraction);
System.out.println();
}
/**
* 打印输出整数
*
* @param n
*/
private static void printOut(int n) {
if (n >= 10) {
printOut(n / 10);
}
System.out.print(n % 10);
}
/**
* 打印输出小数
*
* @param fraction
*/
private static void printDouble(double fraction) {
if (fraction < 1 && fraction >= 0.00001) {
System.out.print((int) (fraction * 10) % 10);
printDouble(fraction * 10 - (int) (fraction * 10));
}
}
编写递归方法,返回数N的二进制表示中1的个数。
方法一:不用递归
/**
* 返回数N的二进制表示中1的个数
*
* @param N
* @return
*/
public static int getOnes(int N) {
int i = 0;
while(N >= 1){
if (N % 2 != 0) {
i++;
}
N = N / 2;
}
return i;
}
方法二:使用递归
/**
* 递归做法,返回数N的二进制表示中1的个数
* @param N
* @return
*/
public static int Ones(int N){
//递归终点有两个,n为1则返回1,n为0则返回0
if(N < 2){
return N;
}
//此为递归过程,如果为奇数,结果加1,如果为偶数,结果加0。
return N % 2 + Ones(N/2);
}
拓展:如何将整数转为二进制数?
/**
* 将整数转为二进制数
*
* @param N
*/
public static void printForOne(int N) {
String str = "";
while (N >= 1) {
str += N % 2;
N = N / 2;
}
//反转
String s = charReverse(str.toCharArray());
System.out.println(s);
}
/**
* 反转字符数组
*
* @param chars
*/
public static String charReverse(char[] chars) {
char[] ch = new char[chars.length];
int j = 0;
for (int i = chars.length - 1; i >= 0; i--, j++) {
ch[j] = chars[i];
}
String string = String.valueOf(ch);
return string;
}