java编程算法经典案例

from:https://www.cnblogs.com/tobiasy/p/9643184.html

一、购物问题

  小明的女朋友最喜欢在网上买买买了,可是钱包里钞票有限,不能想买啥就买啥。面对琳琅满目的物品,她想买尽可能多的种类,每种只买一件,同时总价格还不能超过预算上限。于是她请小明写程序帮她找出应该买哪些物品,并算出这些物品的总价格。

  输入规范:
    每个输入包含两行。第一行是预算上限。第二行是用空格分隔的一组数字,代表每种物品的价格。所有数字都为正整数并且不会超过10000。

  输出规范:
    对每个输入,输出应买物品的总价格。

  输入示例1:
    100
    50 50
  输出示例1:
    100

  输入示例2:
    188
    50 42 9 15 105 63 14 30
  输出示例2:
    160

代码如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

public class BuyTest {

    public static void main(String[] args) {

        //商品价格

        Integer[] ints = {5042915105631430};

        //预算上限

        Integer sum = 188;

        Integer num = calculate(ints, sum);

        System.out.println(num);

    }

    public static Integer calculate(Integer[] ints, Integer sum) {

        Integer count = 0;

        Integer value;

        sort(ints);

        for (Integer integer : ints) {

            value = count;

            count += integer;

            if (count > sum) {

                return value;

            }

        }

        return count;

    }

    public static void sort(Integer[] arr) {

        for (int i = 0; i < arr.length; i++) {

            for (int j = i + 1; j < arr.length; j++) {

                if (arr[i] > arr[j]) {

                    int temp = arr[i];

                    arr[i] = arr[j];

                    arr[j] = temp;

                }

            }

        }

    }

}

 

 二、信息加密(数组偏移)问题

  李雷和韩梅梅坐前后排,上课想说话怕被老师发现,所以改为传小纸条。为了不被老师发现他们纸条上说的是啥,他们约定了如下方法传递信息:
将26个英文字母(全为大写),外加空格,一共27个字符分成3组,每组9个。也就是ABCDEFGHI是第一组,JKLMNOPQR是第二组,STUVWXYZ*是第三组(此处用*代表空格)。
然后根据传递纸条那天的日期,改变字母的位置。
先根据月份数m,以整个分组为单位进行循环左移,移动(m-1)次。
然后根据日期数d,对每个分组内的字符进行循环左移,移动(d-1)次。
以3月8日为例,首先移动分组,3月需要循环左移2次,变成:
STUVWXYZ*,ABCDEFGHI,JKLMNOPQR
然后每组内的字符,8日的话需要循环左移7次,最终的编码为:
Z*STUVWXY,HIABCDEFG,QRJKLMNOP
对于要传递信息中的每个字符,用组号和组内序号两个数字来表示。
如果在3月8日传递信息“HAPPY”,那么H位于第2组的第1个,A位于第2组第3个,P位于第3组第9个,Y位于第1组第9个,所以纸条上会写成:
21 23 39 39 19
现在给定日期和需要传递的信息,请输出应该写在纸条上的编码。

输入规范:
  每个输入包含两行。第一行是用空格分隔的两个数字,第一个数字是月份,第二个数字是日子。输入保证是一个合法的日期。
  第二行为需要编码的信息字符串,仅由A~Z和空格组成,长度不超过1024个字符。

输出规范:
  对每个输入,打印对应的编码,数字之间用空格分隔,每个输出占一行。

  输入示例1:
  1 1
  HI
  输出示例1:
  18 19

  输入示例2:
  3 8
  HAPPY
  输出示例2:
  21 23 39 39 19

  输入示例3:
  2 14
  I LOVE YOU
  输出示例3:
  35 25 18 12 29 31 25 23 12 28

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

package com.tobiasy.toolkit.test;

public class MessageTest {

    public static void main(String[] args) {

        //月份数

        int month = 2;

        //日

        int day = 14;

        //所需要转化的字符

        String text = "I LOVE YOU";

        start(month, day, text);

    }

    public static void start(int month, int day, String text) {

        char[] chars = text.toCharArray();

        for (char c : chars) {

            String value = getChar(month, day, c);

            System.out.print(value + ",");

        }

    }

    public static String getChar(int month, int day, char c) {

        month -= 1;

        day -= 1;

        char[][] chars = {

                {'A''B''C''D''E''F''G''H''I'},

                {'J''K''L''M''N''O''P''Q''R'},

                {'S''T''U''V''W''X''Y''Z'' '}};

        int monthFoward = month % chars.length;

        int dayFoward = day % chars[0].length;

        chars = sort(chars, monthFoward);

        for (int i = 0; i < chars.length; i++) {

            char[] arr = chars[i];

            sort(arr, dayFoward);

        }

        return getCharLocation(chars, c);

    }

    public static String getCharLocation(char[][] chars, char c) {

        String value = "";

        sys:

        for (int i = 0; i < chars.length; i++) {

            for (int j = 0; j < chars[i].length; j++) {

                char ch = chars[i][j];

                if (ch == c) {

                    value = ++i + "" + ++j;

                    break sys;

                }

            }

        }

        return value;

    }

    public static char[] sort(char[] chars, int dayFoward) {

        char[] arr = chars.clone();

        for (int i = 0; i < chars.length; i++) {

            int forward = i + dayFoward >= chars.length ? i + dayFoward - chars.length : i + dayFoward;

            chars[i] = arr[forward];

        }

        return chars;

    }

    public static char[][] sort(char[][] chars, int monthFoward) {

        char[][] arr = chars.clone();

        for (int i = 0; i < chars.length; i++) {

            int forward = i + monthFoward >= chars.length ? i + monthFoward - chars.length : i + monthFoward;

            chars[i] = arr[forward];

        }

        return chars;

    }

}

 三、老鼠走迷宫

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

/**

   * 老鼠走迷宫

   * 说明:

   * 老鼠走迷宫是递回求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1表示老鼠行走的路径,试以程

   * 式求出由入口至出口的路径。

   *

   * 解法:

   * 老鼠的走法有上,下,左,右四个方向,在每前进一格之后就选一个方向前进,无法前进时退回选择下一个可前

   * 进方向,如此在阵列中依序测试四个方向,直到走到出口为至,这是返回的基本题,请直接看程式应就可以理解

   */

  static int[][] maze = {

      {22222222},

      {20000002},

      {20202002},

      {22000202},

      {22020002},

      {22022222},

      {20000002},

      {22222222}

  };

  static int startI = 1, startJ = 1;

  static int endI = 6, endJ = 6;

  static int success = 0;

  public static int walk() {

      int i, j;

      int length = maze[0].length;

      System.out.println("显示迷宫:\n");

      for(i = 0; i < length; i++)

      {

          for(j = 0; j < length; j++)

          {

              if(maze[i][j] == 2) {

                  System.out.print("#");

              else {

                  System.out.print(" ");

              }

          }

          System.out.println("\n");

      }

      if(visit(startI, startJ) == 0) {

          System.out.println("\n没有找到出口!\n");

      else {

          System.out.println("\n显示路径:\n");

          for(i = 0; i < length; i++)

          {

              for(j = 0; j < length; j++)

              {

                  if(maze[i][j] == 2) {

                      System.out.print("#");

                  else if(maze[i][j] == 1) {

                      System.out.print("1");

                  else {

                      System.out.print(" ");

                  }

              }

              System.out.println("\n");

          }

      }

      return 0;

  }

  private static int visit(int i, int j) {

      maze[i][j] = 1;

      if(i == endI && j == endJ) {

          success = 1;

      }

      if(success != 1 && maze[i][j+1] == 0) {

          visit(i, j+1);

      }

      if(success != 1 && maze[i+1][j] == 0) {

          visit(i+1, j);

      }

      if(success != 1 && maze[i][j-1] == 0) {

          visit(i, j-1);

      }

      if(success != 1 && maze[i-1][j] == 0) {

          visit(i-1, j);

      }

      if(success != 1) {

          maze[i][j] = 0;

      }

      return success;

  }

四、八皇后问题

说明:
西洋棋中的皇后可以直接前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上,
1970年与1971年,E.W.Dijkstra与N.Wirth曾经用这个问题来讲解程式设计之技巧。

解法:
关于棋盘的问题,可以用递回求解,然而如何减少递回的次数?在八个皇后额问题中,不必要所有的个子都检查过,例如若某列
检查过,该列的其他格子就不用再检查了,这个方法称为分支修剪。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

package com.tobiasy.toolkit.algorithm;

/**

 * @author tobiasy

 * @date 2018/10/29

 */

public class EightQueen {

    public static void main(String[] args) {

        queen();

    }

  

    static final Integer N = 8;

    /**

     * 同栏是否有皇后,1表示有

     */

    static int[] column = new int[N+1];

    /**

     * 右上至左下是否有皇后

     */

    static int[] rup = new int[2*N+1];

    /**

     *  左上至右下是否有皇后

     */

    static int[] lup = new int[2*N+1];

    static int[] queen = new int[N+1];

    /**

     * 解答编号

     */

    static int num;

  

  

    private static int queen() {

        int i;

        num = 0;

  

        for(i = 1; i <= N; i++)

        {

            column[i] = 1;

        }

  

        for(i = 1; i <= 2*N; i++)

        {

            rup[i] = lup[i] = 1;

        }

  

        backtrack(1);

  

        return 0;

    }

  

    private static void showAnswer() {

        int x, y;

        System.out.print("\n解答 "+ ++num+"\n");

        for(y = 1; y <= N; y++) {

            for(x = 1; x <= N; x++)

            {

                if(queen[y] == x)

                {

                    System.out.print("●");

                }

                else

                {

                    System.out.print("◎");

                }

            }

            System.out.print("\n");

        }

    }

     

    private static void backtrack(int i) {

        int j;

  

        if(i > N)

        {

            showAnswer();

        }

        else

        {

            for(j = 1; j <= N; j++)

            {

                if(column[j] == 1 && rup[i+j] == 1 && lup[i-j+N] == 1)

                {

                    queen[i] = j;

                    column[j] = rup[i+j] = lup[i-j+N] = 0;

                    backtrack(i+1);

                    column[j] = rup[i+j] = lup[i-j+N] = 1;

                }

            }

        }

    }

}

五、字符串最长对称子串

说明:
  输入一段字符串,求其最长的对称子串并输出;例:
输入:qabccbaff,输出:abccba
出入:pop-upu,  输出:pop和upu

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

import java.util.ArrayList;

import java.util.List;

/**

 * 找出最长对称字符串

 *

 * @author tobiasy

 */

public class MaxSymmetric {

    public static void main(String[] args) {

        // TODO 输出最长对称字符串:goog

        String input1 = "google";

        // TODO 输出最长对称字符串:aba

        String input2 = "abada";

        // TODO 输出2个最长对称字符串:pop/upu

        String input3 = "pop-upu";

        start("sdghjdgzzgdah");

    }

    /**

     * 启动方法

     * @param str

     */

    private static void start(String str) {

        List<String> list = maxSubSymmetric(str);

        if (list.isEmpty()) {

            System.err.println("没有找到对称字串!");

        }

        list.forEach(System.out::println);

    }

    /**

     *  获取字符串中最长的对称字串

     * @param str

     * @return

     */

    private static List<String> maxSubSymmetric(String str) {

        List<String> result = new ArrayList<>();

        List<String> list = allSubSymmetric(str);

        Integer length = 0;

        for (String s : list) {

            if (s.length() > length) {

                length = s.length();

            }

        }

        for (String s : list) {

            if (s.length() >= length) {

                result.add(s);

            }

        }

        return result;

    }

    /**

     * 获取所有的对称字串

     * @param str

     * @return

     */

    private static List<String> allSubSymmetric(String str) {

        List<String> list = new ArrayList<>();

        for (int i = 0; i <= str.length(); i++) {

            for (int j = i; j <= str.length(); j++) {

                String sub = str.substring(i, j);

                if (check(sub)) {

                    list.add(sub);

                }

            }

        }

        return list;

    }

    /**

     * 判断字符串是否对称

     * @param str

     * @return

     */

    private static boolean check(String str) {

        if (str == null || str.length() <= 1) {

            return false;

        }

        for (int i = 0; i < str.length(); i++) {

            if (str.charAt(i) != str.charAt(str.length() - i - 1)) {

                return false;

            }

        }

        return true;

    }

}

 六、模拟手机号注册

 
说明:
利用面向对象思路,设计和完成“手机号注册校验”业务逻辑。

你需要校验多种情况的用户输入,如:

输入:13812341234 提示注册成功

输入:1381234abcd 提示非法手机号码

输入:138 1234 1234 提示注册成功

再次输入:13812341234 提示该手机号已被注册

-- 涉及到缓存请自行选择

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

package com.tobiasy.toolkit.algorithm;

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

/**

 * 用户手机号注册校验

 *

 * @author tobiasy

 */

public class PhoneRegister {

    /**

     * 缓存地址

     */

    private static final String FILE_PATH = "E://test/data";

    public static void main(String[] args) {

        String phoneNum1 = "138 1234 1234";

        String phoneNum2 = "13812345abc";

        String phoneNum3 = "13812345678";

        String phoneNum4 = "1381234 5678";

        String phoneNum5 = "98765432101";

        start(phoneNum3);

    }

    /**

     * 启动方法

     * @param phone

     */

    private static void start(String phone){

        if (check(phone)) {

            register(format(phone));

        else {

            err("非法手机号码!");

        }

        out(String.format("已注册账号:%s", getRegisterPhoneNums()));

    }

    private static void err(Object o) {

        System.err.println(o);

    }

    private static void out(Object o) {

        System.out.println(o);

    }

    /**

     * 创建文件

     * @return

     */

    private static boolean createFile() {

        File file = new File(FILE_PATH);

        if (!file.exists()) {

            try {

                File parentFile = file.getParentFile();

                if (!parentFile.exists()) {

                    parentFile.mkdirs();

                }

                file.createNewFile();

            catch (IOException e) {

                return false;

            }

        }

        return true;

    }

    /**

     * 反序列化

     * @return

     */

    private static Object getRegisterPhoneNums(){

        return SerializableUtils.read(FILE_PATH);

    }

    /**

     * 格式化手机号码

     * @param phoneNum

     * @return

     */

    private static String format(String phoneNum){

        return phoneNum.replaceAll("( )\\1*""");

    }

    /**

     * 注册

     * @param phoneNum

     */

    public static void register(String phoneNum) {

        try {

            if (!createFile()) {

                err("缓存文件地址错误!");

            else {

                List<String> data;

                Object object = SerializableUtils.read(FILE_PATH);

                if (object != null) {

                    data = (List<String>) object;

                    boolean contains = data.contains(phoneNum);

                    if (contains) {

                        err("该手机号已被注册!");

                    else {

                        data.add(phoneNum);

                        out("注册成功!");

                    }

                else {

                    data = new ArrayList<>();

                    data.add(phoneNum);

                    out("注册成功!");

                }

                SerializableUtils.write(data, FILE_PATH);

            }

        catch (Exception e) {

            err("序列化异常!");

        }

    }

    /**

     * 校验手机号码是否正确

     * @param phoneNum

     * @return

     */

    private static boolean check(String phoneNum) {

        return phoneNum.matches("1(3[0-9]|5[189]|8[6789])( )?[0-9]{4}( )?[0-9]{4}");

    }

}

 工具类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

package com.tobiasy.toolkit.algorithm;<br>

import java.io.*;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

/**

 * JDK自带序列化操作

 *

 * @author tobiasy

 */

public class SerializableUtils {

    /**

     * 序列化 将对象存储到文件中

     *

     * @param obj  序列化对象,必须实现可序列化接口

     * @param path 序列化路径

     * @return

     */

    public static boolean write(Object obj, String path) {

        boolean f;

        File file = getFile(path);

        OutputStream out null;

        ObjectOutputStream objout = null;

        try {

            out new FileOutputStream(file);

            objout = new ObjectOutputStream(out);

            objout.writeObject(obj);

            f = true;

        catch (IOException e) {

            f = false;

            e.printStackTrace();

        finally {

            close(objout);

            close(out);

        }

        return f;

    }

    /**

     * 反序列化 读取存入文件中的对象

     *

     * @param pathname 反序列化路径

     * @return

     */

    public static Object read(String pathname) {

        Object obj = null;

        File file = new File(pathname);

        InputStream in null;

        ObjectInputStream objin = null;

        try {

            in new FileInputStream(file);

            objin = new ObjectInputStream(in);

            obj = objin.readObject();

        catch (ClassNotFoundException e) {

            e.printStackTrace();

        catch (EOFException e) {

        catch (IOException e) {

            e.printStackTrace();

        finally {

            close(objin);

            close(in);

        }

        return obj;

    }

    public static File getFile(String filePath) {

        File file = new File(filePath);

        if (!file.exists()) {

            try {

                file.createNewFile();

            catch (IOException e) {

                e.printStackTrace();

            }

        }

        return file;

    }

    /**

     * 流的关闭操作

     *

     * @param obj 流对象

     */

    public static void close(Object obj) {

        if (obj != null) {

            try {

                invoke(obj, "close");

            catch (RuntimeException e) {

                e.printStackTrace();

            }

        }

    }

    /**

     * 执行一个无参方法

     *

     * @param obj        操作对象

     * @param methodName 属性名

     * @return Object

     * @throws RuntimeException

     */

    public static Object invoke(Object obj, String methodName) throws RuntimeException {

        if (obj == null || methodName == null) {

            return null;

        }

        Object value = null;

        try {

            Method getMethod = obj.getClass().getMethod(methodName);

            if (getMethod == null) {

                return null;

            }

            getMethod.setAccessible(true);

            value = getMethod.invoke(obj);

        catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {

            e.printStackTrace();

        }

        return value;

    }

}

发布了176 篇原创文章 · 获赞 1 · 访问量 7137

猜你喜欢

转载自blog.csdn.net/qq_37769323/article/details/104216460