算法——暴力之美(volence‘s beautify of algorithm)

暴力算法(volence’s beautify of algorithm)

  • 思想:利用暴力法的思想找到所有的解,然后从中选出符合问题要求的解
  • 算法总结:暴力法的优点是实现简单,容易编程,但是往往会消耗更多的时间和空间资源,因此大多数暴力法还要根据应用背景尽力改进
找到问题的所有的解筛选出符合题意的解
  1. 全排列问题:

给定数据k,请依照样例,输出其全排列
思路:设置一个数组来存储1-k的数字,然后再设置一个数组记录每个数字的访问情况,
最后用一个栈来记录访问的路径,再依次深度递归,并修改标记,递归回程时恢复标记,
如果栈的大小大于k则输出此次排列,直到递归到所有的子树
样例1:
3
输出:
123
132
213
231
312
321
样例2:
4
输出:
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
代码如下:

思路:设置一个数组来存储1-k的数字,然后再设置一个数组记录每个数字的访问情况,
最后用一个栈来记录访问的路径,再依次深度递归,并修改标记,递归回程时恢复标记,
如果栈的大小大于k则输出此次排列,直到递归到所有的子树
样例13
输出:
123
132
213
231
312
321
样例24
输出: 
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
代码如下:

import java.util.Scanner;

// Created by Chenglong Shi on 2021/10/19.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
public class AllPermutation {
    static final int ma=10;
    static int n,top=0;
    static int []a=new int[ma];
    static int []st=new int[ma];
    static int []vis=new int[ma];
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        for(int i=0;i<n;i++) a[i]=i+1;
        getPermutation(1);
        in.close();
    }
    public static void show(){
        for(int i=0;i<top;i++) System.out.print(st[i]);
        System.out.println();
    }
    public static void getPermutation(int floor){
        if(floor>n){
            show();
            return;
        }
        for(int i=0;i<n;i++){
            if(vis[i]==0){
                st[top++]=a[i];
                vis[i]=1;
                getPermutation(floor+1);
                top--;
                vis[i]=0;
            }
        }
    }
}


  1. 快速幂问题:

给定数据a和b在给定时间内输出a的b次方
思路:用递归的方式编程,用long类型来存储数据,每次将b折半,直到b的值为1的时候,返回a的值,然后在每次回溯中判断b是偶数还是奇数,如果是偶数则返回上一层函数返回的值的平方,否则返回上一层值的平方乘以a。当回溯完毕后返回的就是a的b的次方
样例1:
3 8
输出
6561
样例2:
2 4
输出:
16
代码如下:

// Created by Chenglong Shi on 2021/10/16.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:递归
//
import java.util.Scanner;

public class fast_power {
    private static long a;
    private static long b;
    public static void main(String[] args) {
        Scanner in =new Scanner(System.in);
        while(in.hasNext()){
            a=in.nextLong();
            b=in.nextLong();
            System.out.println(fast_power(b));
        }
        in.close();
    }
    public static long fast_power(long b){
        if(b<=1) return a;
        long temp=fast_power(b/2);
        if(b%2==0) return temp*temp;
        else return temp*temp*a;
    }
}

  1. 幂集问题

输入一个数k,输出集合元素为1-k的集合的子集
思路:用二进制的方式每次测试0-2的k次方的相于运算的结果,如果相与的结果大于等于0,则表示此时相与元素是当前目标集合的元素,循环结束后即可输出所有的子集,同时使用二进制的方式可以加速程序的运行
输入样例1:
3
输出:
{}
{1}
{2}
{3}
{1,2}
{1,3}
{2,3}
{1,2,3}
输入样例2:
2
输出:
{}
{1}
{2}
{1,2}
代码如下:

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

// Created by Chenglong Shi on 2021/10/16.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:二进制获得幂集
// Copyright (c) 2021 幂集的获得. All rights reserved.
//
public class pow_set {
    private static int n,index=1;
    static final int ma=1080;
    static String []result=new String[ma];
    public static void main(String[] args) {
        for(int i=0;i<ma;i++) result[i]="-";
        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        int len=(int)Math.pow(2,n);
        getsq();
        Arrays.sort(result,1,len, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String k1=(String) o1,k2=(String) o2;
                if(k1.length()==k2.length()) return k1.compareTo(k2);
                else return k1.length()-k2.length();
            }
        });
        show(len);
        in.close();
    }
    public static void getsq(){
       for(int i=0;i<(1<<n);i++){
           String m="{";
           for(int j=0;j<n;j++){
               if((i&(1<<j))>0)
               {
//                   System.out.println("j is:"+j);
                   if(m.length()==1) m+=String.valueOf(j+1);
                   else m+=(","+String.valueOf(j+1));
               }
           }
           m+="}";
//           System.out.print("m is:"+m);
//           System.out.println("---------------");
           result[index++]=new String(m);
       }
    }
    public static void show(int len){
        for(int i=1;i<=len;i++)
            if(result[i].length()>0){
                System.out.println(result[i]);
            }
    }
}

  1. n皇后

输入n,代表n个皇后,放置的规则是每个皇后不同行,不同列,不同左右对角线,输出其对应的所有解。
思路:用回溯的方法先一行一行的放,然后列数从1开始,判断此行当前列是否与前面的列和对角线冲突,如果冲突,立即放弃本次放置,再判断其他的放置方式。如果放置n个后就输出这个方案
输入样例1:
6
输出:
1: (1,2) (2,4) (3,6) (4,1) (5,3) (6,5)
2: (1,3) (2,6) (3,2) (4,5) (5,1) (6,4)
3: (1,4) (2,1) (3,5) (4,2) (5,6) (6,3)
4: (1,5) (2,3) (3,1) (4,6) (5,4) (6,2)
输入样例2:
4
输出:
1: (1,2) (2,4) (3,1) (4,3)
2: (1,3) (2,1) (3,4) (4,2)
代码如下:

// Created by Chenglong Shi on 2021/10/17.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
import java.util.Scanner;

public class n_queens {
    static int n;
    final static int ma=20;
    static int index=1;
    static int []col=new int[ma];//最大15行15列
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        pushQueen(1);
        in.close();
    }
    static void pushQueen(int rows){
        if(rows>n) show();
        for(int j=1;j<=n;j++){
            if(isCanPut(rows,j)){
                col[rows]=j;
                pushQueen(rows+1);
            }
        }
    }
    static void show(){
        System.out.print(index+": ");
        for(int i=1;i<=n;i++)
            if(i==1) System.out.print("("+i+","+col[i]+")");
            else System.out.print(" ("+i+","+col[i]+")");
            System.out.println();
            index++;
    }
    static boolean isCanPut(int i,int j){
        if(i==1) return true;
        int pre=1;
        while(pre<i){
            if(col[pre]==j||(Math.abs(i-pre)==Math.abs(j-col[pre])))
                return false;
            pre++;
        }
        return true;
    }
}

  1. 约瑟夫问题

一堆人(n个人)坐在一个圆桌上,每次从1开始数,数到m的人自动请出圆桌,然后下一个人借着从1开始数,一直做上述的步骤,现在请你输出,最后剩下的那个人的编号。
思路:利用取模的思想来求出每次需要剔除的人的编号,剔除后,相当于桌子变小,然后进一步取模,直到桌子的大小变为1,然后输出剩下的那个人的编号即可。
输入样例1:
6 2
输出:
5
输入样例2:
12 4
输出:
1
代码如下:

import java.util.ArrayList;
import java.util.Scanner;
public class yue_se_fu {
    static int n,m;
    static ArrayList<Integer> arr=new ArrayList<Integer>();
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        while(true){
            n=in.nextInt();
            m=in.nextInt();
            if(n==0&&m==0) break;
            arr.clear();
            for(int i=1;i<=n;i++) arr.add(i);
            manageCircle(arr);
        }
        in.close();
    }
    static void manageCircle(ArrayList<Integer> arr){
        int index=0;
        while(arr.size()>0){
            if(arr.size()==1){
                System.out.println(arr.get(0));
                break;
            }
            index=(index+m-1)% arr.size();
            arr.remove(index);
        }
    }
}

  1. 排列组合问题

输入m和n,输出排列数和组合数(排列数A(m,n),组合数C(m,n))
思路:根据公式A(m,n)=n!/(n-m)! B(m,n)=A(m,n)/m!,设计出一个求阶乘的函数,然后化简带入到公式即可求出,排列数和组合数。
输入样例1:
4 4
输出:
24 1
输入样例2
3 4
输出:
24 4
代码如下:

import java.util.Scanner;
// Created by Chenglong Shi on 2021/10/19.
// Only can use to study
// Once found commercial or illegal use will be pursued to the end
// Banning plagiarism
// Email:2230307855@qq.com
// 内部可能含有拼音和汉语注释
// by 史成龙
// 方法:
//
public class permutation_and_combination {
    static long m,n;
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        m=in.nextLong(); n=in.nextLong();
        if(m==0&&n==0) System.out.println("0 0");
        else
        System.out.println(get_Permutation()+" "+get_combination());
        in.close();
    }
    static long getJieCheng(long be,long en){
        if(be==0) return 1;
        long num=be;
        for(long k=be+1;k<=en;k++) num*=k;
        return num;
    }
    static long get_Permutation(){
        long deli=n-m;
        if(deli==n) return 1;
        else if(deli==0) return getJieCheng(1,n);
        else return getJieCheng(n-m+1,n);
    }
    static long get_combination(){
        return get_Permutation()/getJieCheng(1,m);
    }
}

  • 希望大家多去理解理解西靠思考将其转换为自己得知识,感谢大家一起努力!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SweetCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值