【问题标题】:Is there a way to use binary search to get a specific outcome有没有办法使用二进制搜索来获得特定的结果
【发布时间】:2020-11-13 07:29:25
【问题描述】:

我的代码有效,但它仅适用于初始切割值。我应该在 getLetterGrade 方法中使用二进制搜索算法来获得所需的结果,但每次我都只能得到一个结果。

Spring bean 类

public class Grade implements GradeI {
    private String name;
    private int[] gradeBoundary = {100, 90, 85, 80, 77, 73, 70, 0};
    private String[] gradeLetter = {"A+", "A", "A-", "B+", "B", "B-", "F"};
    private int count = 8;
    //private int key = 50;
    int result = Arrays.binarySearch(gradeBoundary, 80);
    private String gradeLetterValue = null;

    public Grade() {
    }


    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setGradeBoundary(int[] grade) {
        this.gradeBoundary = grade;
    }

    public int[] getGradeBoundary() {
        return gradeBoundary;
    }

    public void setGradeLetter(String[] gradeLet) {
        this.gradeLetter = gradeLet;
    }

    public String[] getGradeLetter() {
        return gradeLetter;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getCount() {
        return count;
    }

    public String getLetterGrade(int numerical_grade) {

        if (numerical_grade < 70) {
            gradeLetterValue = "F";
        } else if (numerical_grade < 73) {
            gradeLetterValue = "B-";
        } else if (numerical_grade < 77) {
            gradeLetterValue = "B";
        } else if (numerical_grade < 80) {
            gradeLetterValue = "B+";
        } else if (numerical_grade < 85) {
            gradeLetterValue = "A-";
        } else if (numerical_grade < 90) {
            gradeLetterValue = "A";
        } else if (numerical_grade < 100) {
            gradeLetterValue = "A+";
        }

        return gradeLetterValue;
    }
}
    

主类

public class GradeApp {
            
public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext("GradeBeans.xml");
                Grade obj = (Grade) context.getBean("grade-bean");
                
                
                for(int i =66; i <=100; i++) {
                    
                    System.out.println(i+":"+ obj.getLetterGrade(i));
                }
        }
  }

The desired outcome is like this : 

66:F 67:F 68:F 69:F 70:B- 
71:B- 72:B- 73:B 74:B 75:B 
76:B 77:B+ 78:B+ 79:B+ 80:A- 
81:A- 82:A- 83:A- 84:A- 85:A 
86:A 87:A 88:A 89:A 90:A+ 
91:A+ 92:A+ 93:A+ 94:A+ 95:A+ 
96:A+ 97:A+ 98:A+ 99:A+ 100:A+ 

以下是我对二分搜索的尝试,当我在主程序中运行此代码时,我得到的唯一结果是 B+

    public String getLetterGrade(int numerical_grade) {
        int result = Arrays.binarySearch(gradeBoundary, 0, 7, 80);

        if (result == 6) {
            gradeLetterValue = "F";
        } else if (result == 5) {
            gradeLetterValue = "B-";
        } else if (result == 4) {
            gradeLetterValue = "B";
        } else if (result == 3) {
            gradeLetterValue = "B+";
        } else if (result == 2) {
            gradeLetterValue = "A-";
        } else if (result == 1) {
            gradeLetterValue = "A";
        } else if (result == 0) {
            gradeLetterValue = "A+";
        }

        return gradeLetterValue;
    }

我的问题是如何使用二进制搜索来获得所需的结果

更新

最适合我的解决方案是创建自己的二进制搜索算法并使用它来查找字母,如下面的代码

public String getLetterGrade(int numerical_grade) {
        int low = 0;
        int index = count - 1;
        int max = (low + index) / 2;
        while (low < index - 1) {
            max = (low + index) / 2;
            if (this.gradeBoundary[max] <= numerical_grade)
                index = max;
            else
                low = max;
        }
        if (low == index - 1) max = low;
        return gradeLetter[max];
    }

【问题讨论】:

  • 如果我将代码格式化为可读状态,你会反对吗?
  • 完全没有,如果更容易阅读的话
  • 好的,完成,这实际上是你的工作。现在看起来 switch 语句将是比所有这些 if 更好的选择。或者Map&lt;Integer, String&gt; 没有考虑过这个问题。顺便说一句,IDE 有自动格式化命令。

标签: java binary-search spring-bean


【解决方案1】:

如果你想使用Arrays.binarySearch:

  1. 来自Arrays.binarySearchjavadoc:

使用二进制搜索算法在指定的整数数组中搜索指定的值。 在进行此调用之前,必须对数组进行排序(如通过 sort(int[]) 方法)(选择是我的)

Arrays.sort(int[])升序 顺序对数组进行排序,因此要使用Arrays.binarySearch,您应该对gradeBoundary 数组进行升序而不是降序排序。

  1. 如果您的数组中没有key,则Arrays.binarySearch 返回-insertion_point - 1。插入点是一个索引,您可以在其中插入key,以便您的数组仍然可以排序。 gradeLetter 数组中的等级索引在插入点之前。

总而言之,此代码按预期工作(假设您按升序对gradeBoundary 进行了排序):

// 100 is not really a boundary here so maybe we can remove it from array
private int[] gradeBoundary = {0, 70, 73, 77, 80, 85, 90};
private String[] gradeLetter = {"F", "B-", "B", "B+", "A-", "A", "A+"};

public String getLetterGrade(int numericalGrade) {
    int result = Arrays.binarySearch(gradeBoundary, numericalGrade);

    if (result < 0) {
        // (-result - 1) is an insertion point, -1 to get
        // the index of corresponding grade
        result = (-result - 1) - 1;
    }

    gradeLetterValue = gradeLetter[result];

    return gradeLetterValue;
}

【讨论】:

    【解决方案2】:

    您可以通过更好的边界数组获得边界的字母等级索引,只需修改二进制搜索算法即可返回区间上边界的索引。由于当left>right时二分搜索将超出while,left将是上边界的索引。如果找到 key,则返回 key 的索引为 mid。因此,您只需将return -1 更改为return left。而letters[findUpperBoundaryIndex(boundaries,grade)]应该给出相应的字母等级。

    int[] boundaries = {69, 72, 76, 79, 84, 89, 100};
    String[] letters = {"F", "B-", "B", "B+", "A-", "A", "A+"};
    
    int findUpperBoundaryIndex(int[] arr, int key) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right-left)/2;
            if (arr[mid] == key) {
                return mid;
            }
            if (arr[mid] < key) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
    
    gradeLetterValue = letters[findUpperBoundaryIndex(boundaries,grade)];
    

    【讨论】:

      猜你喜欢
      • 2017-04-02
      • 1970-01-01
      • 2013-04-06
      • 2021-08-22
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      相关资源
      最近更新 更多