1.问题描述
2.思路分析:
首先这是一个固定的四位数,需要将数字从小到大排列起来,这是需要解决的第一个问题,所以我们容易想到的是将这个输入的数字拆分各个数字位,然后保存到一个整型数组中,接下来异步是需要将这个数组中的数字进行从大到小排序,其中我使用到的方法:利用两个循环,其中第一个循环中把最大值赋值给当前正在循环的变量i,其次进入第二个循环,第二个循环中的j加1 意思是往后退一步,寻找出比当前的a[i]要大的那个数,加入找到就需要替换这两个数字的位置:(并且最大的数不是本身才替换)
然后是要将数组中这种排列好的从大到小排列的数字减去从小到大的数字,这里要注意一下假如该位数字不够减需要向高位借位,并将结果保存到一个数组c中,因为后面循环判断是是否找到的时候要使用
接下里需要将数组c中最新存放的倒数四个数字赋给a数组,因为循环不知道什么时候就结束,所以有可能进入下一次的循环,此时a[]数组保存的应该是c数组中最新存放的倒数四个数字
下面进行判断是否找到c数组中与前面数字一模一样的,但是怎么样去判断呢?
因为我们每一次判断都是判断存放在c数组中的倒数最后四个字符与前面的字符是否出现得一模一样,假如一模一样就要退出循环,有一个关键的问题就是什么时候一模一样呢?这里采用的是每四个字符为一个内层循环,外层循环的次数就应该为所有的字符数除以4 - 1,因为只需要判断本身与前面的字符是否相同,但是什么时候每一次内层循环结束都需要判断字符长度标志是否为4,假如不是4,继续下一次4个字符的判断,还有一个重要的是千万要将字符长度重置为0,如果是4跳出循环,设置一个表示记录为true,为最外层的循环跳出最好准备,最外层的循环一判断跳出标志为true,立即跳出循环
3.代码实现:
import java.util.Scanner;
public class 六一七四问题 {
public static void main(String[] args) {
int a[] = new int[4];
int b[] = new int[4];
int c[] = new int[1000];
int len = 0;
int count = 0;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.print(n+"->");
int max = 0;
int flag = 0;
boolean fg = false;
int middle;
for(int i = 0;n!=0;i++){
a[i] = n % 10;
n = n / 10;
}
while(true){
for(int i = 3;i>=0;i--){
max = a[i];
for(int j = i-1;j>=0;j--){
if(max<a[j]){
max = a[j];
flag = j;
}
}
if(max!=a[i]){
middle = a[i];
a[i] = a[flag];
a[flag] = middle;
}
}
for(int i = 3;i>=0;i--){
b[i] = a[3-i];
}
for(int i = 0;i<4;i++){
if(a[i] -b[i]<0){
a[i+1]--;
c[count++] = a[i] + 10 - b[i];
}
else{
c[count++] = a[i] -b[i];
}
}
for(int i = 0,k=count-1;i<4;i++){
System.out.print(c[k--]);
}
for(int i = 0,k = count-4;i<4;i++){
a[i] = c[k++];
}
if(count>4){
int e = 0;
for(int i = 0;i<count/4-1;i++){
for(int j =count - 4;j<count;j++){
if(c[e++]==c[j]){
len++;
}
}
if(len==4){
fg = true;
break;
}
len = 0;
}
}
if(fg){
break;
}
System.out.print("->");
}
}
}
4.运行结果截图:
在调试的过程中需要确保上一步是做正确的,才来做下一步的工作,否则会调试很久的,找不出错误在哪里,
后来发现让从大到小排列数组可以不需要上面我这样写,因为上面排列的大小的代码有写代码是累赘的,我们可以这样写:
for(int i = 3;i>=0;i--){
for(int j = i-1;j>=0;j--){
if(a[i]<a[j]){
middle = a[i];
a[i] = a[j];
a[j] = middle;
}
}
}
可以更加简洁,看了题目c++的解答之后,发现思路大部分是一样,它是这样解答的
下面是基于Java代码模仿上面的实现:
import java.util.Scanner;
public class Main {
static int num[] = new int [2000];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
num[0] = sc.nextInt();
System.out.print(num[0]);
int count = 1;
int found = 0;
for(;;){
num[count] = get_next(num[count-1]);
System.out.print("->"+num[count]);
for(int i = 0;i<count;i++){
if(num[i]==num[count]){
found = 1;
break;
}
}
if(found==1){
break;
}
count++;
}
}
private static int get_next(int num) {
int a,b,n;
char t;
char s[] = new char[10];
s = Integer.toString(num).toCharArray();
n = s.length;
for(int i = 0;i<n;i++){
for(int j = i+1;j<n;j++){
if(s[i]<s[j]){
t = s[i];
s[i] = s[j];
s[j] = t;
}
}
}
a = Integer.parseInt(new String(s));
for(int i = 0;i<n/2;i++){
t = s[i];
s[i] = s[n-1-i];
s[n-1-i] = t;
}
b = Integer.parseInt(new String(s));
return a - b;
}
}
其中一开始的时候把倒序字符串的时候n忘记除以二了,导致交换前后的字符串相等,转换成数字也相等,所以全部变成0了,所以在交换的时候只需要交换n/2次,因为一次交换两个字符改变,通过上面的代码我们发现比第一次的要简洁,而且将数字转换成字符串之后更容易操作