折半查找
package com.jetta.third;
/**
* @ClassName BinarySearch
* @Description 二分查找
* @Date 2022/11/19 12:13
* @Version V1.0
**/
public class BinarySearch {
/**
* 二分查找的条件:n个元素有序且连续的存放到数组里面
*
* @param list
* @param left
* @param right
* @param k 要找的值
* @return 要找的值的下标
*/
public static int get(int[] list, int left, int right, int k) {
if (left == 0 && right == 0) {
left = 0;
right = list.length - 1;
}
if (left == right) {
return left;
}
int mid = (left + right) / 2;
if (list[mid] > k) {
right = mid - 1;
} else if (list[mid] < k) {
left = mid + 1;
}
if (list[mid] == k) {
return mid;
}
int i = get(list, left, right, k);
if (list[i] == k) {
return i;
}
return -1;
}
public static void main(String[] args) {
int[] x = {2, 4, 8, 9, 15, 20, 37, 40, 41,
55, 66, 77, 88, 101, 123, 145, 156, 167, 178, 200}; // 9 19 28/2 = 14
System.out.println(get(x, 0, 0, 200));
}
public int getByFor(int[] list, int k) {
int left= 0;
int right = list.length - 1;
if(list[left] == k) {
return left;
}
if(list[right] == k) {
return right;
}
int result = -1;
while (left != right) {
int mid = (left + right) / 2;
if(list[mid] > k) {
right = mid - 1;
}else if(list[mid] < k) {
left = mid + 1;
}else if(list[mid] == k) {
return mid;
}
}
if(list[right] == k) {
return right;
}
return result;
}
}
二分法
package com.jetta.second.divideAndConquer;
/**
* @ClassName divideAndConquer
* @Description 二分法
* @Date 2022/10/24 23:10
* @Version V1.0
**/
public class divideAndConquer {
/**
* 1.思想:其想法是把问题分成两个大致相等的子问题,然后递归地对它们求解,这是“分”的部分。
* “治:阶段将两个子问题的解修补到一起并可能再做些少量的附加工作,最后得到整个问题的解
* 2。递归调用过程一般形式是传递输入的数组以及左边界和右边界,它们界定了数组要被处理的部分。
* 单行驱动程序通过传递数组以及边界0和N-1而将该过程启动。
* 3.有序列 {4, -3 , 5, -2, -1, 2, 6, -2}
* 4.求最大子序列和
*
* 5. 对运行时间进行分析
* 1) 令T(N) 是求解大小为N的最大子序列和问题所花的时间。
* 2) 当 N =1是, 从36行到42行 最多花费 4个时间单元,但是常数不重要,
* 可以说是 T(1) = 1;
* 3) 如果 N > 1, 程序必须运行两个递归调用,两个for循环,以及某些小计量;
* 两个for循环总共接触到 A(0) 到 A(N-1) 每一个元素,而在循环内部工作量是常量,记为O(N);
* 44、45行求解大小为 N/2的子序列问题(假设N是偶数),因为这两行每行花费T(N/2)个时间单元,共2T(N/2)个时间单元;
* 总共所花的时间单元 为 T(N) = 2T(N/2) + O(N);
*
* 得到方程组: T(N) = 2T(N/2) + O(N);
* T(1) = 1;
* 解答过程省略(第七 5章详细求解),答案为 T(N) = O(N logN)
*/
private static int maxSumRec(int[] a, int left, int right) {
// left = right 时,只有一个元素,且当该非负时它就是最大子序列
// 退出递归
if(left == right) {
if(a[left] > 0) {
return a[left];
}else {
return 0;
}
}
int center = (left + right) / 2;
int maxLeftSum = maxSumRec(a, left, center);
int maxRightSum = maxSumRec(a, center, right);
int maxLeftBorderSum = 0, leftBorderSum = 0;
for(int i = center ; i >= left ; i--) {
leftBorderSum = leftBorderSum + a[i];
if(leftBorderSum > maxLeftBorderSum) {
maxLeftBorderSum = leftBorderSum;
}
}
int maxRightBorderSum = 0, rightBorderSum = 0;
for( int i = center + 1 ; i <= right ; i++) {
rightBorderSum = rightBorderSum + a[i];
if(maxLeftBorderSum < rightBorderSum) {
maxRightBorderSum = rightBorderSum;
}
}
// maxRightBorderSum + maxLeftBorderSum 就是左右两部分的最大和
// max3()未完成
return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
}
private static int max3(int maxLeftSum, int maxRightSum, int i) {
return 0;
}
public static int maxSubSum3(int[] a) {
return maxSumRec(a, 0, a.length -1);
}
}
···
## 判断是否回文字符串
···java
package com.jetta.pretty_data_structure;
/**
* @ClassName LeetCode9Palindrome
* @Description 判断是否回文字符串
* @Date 2023/4/16 22:19
* @Version V1.0
**/
public class LeetCode9Palindrome {
public boolean isPalindrome(String str) {
if(str.isEmpty() ) {
throw new IndexOutOfBoundsException();
}
if(str.length() < 2) {
return true;
}
char[] chars = str.toCharArray();
int right = chars.length / 2;
int left;
if(chars.length % 2 == 0) {
left = right-1;
}else {
left = right -1;
right = right +1;
}
int size = left;
for (int i = 0; i <= size; i++) {
if(chars[left] != chars[right]) {
return false;
}
right++;
left--;
}
return true;
}
/**
* 力扣题解
* 1.如果是负数则一定不是回文数,直接返回 false
* 2.如果是正数,则将其倒序数值计算出来,然后比较和原数值是否相等
* 3.如果是回文数则相等返回 true,如果不是则不相等 false
* 4.比如 123 的倒序 321,不相等;121 的倒序 121,相等
*/
class Solution {
public boolean isPalindrome(int x) {
if(x < 0)
return false;
int cur = 0;
int num = x;
while(num != 0) {
cur = cur * 10 + num % 10;
num /= 10;
}
return cur == x;
}
}
}
子序列和最佳算法
package com.jetta.second.divideAndConquer;
/**
* @ClassName BestAnswer
* @Description 子序列和最佳算法
* @Date 2022/10/26 22:33
* @Version V1.0
**/
public class BestAnswer {
/**
* 1.该算法的优点是:它只对数据进行一次扫描,一旦a[i]被读入并被处理,就不需要再记忆,因此
* 如果数组在磁盘上或通过互联网传送,那么它就可以被按顺序读入,在主存中不必存储数组的任何部分。
* 不仅如此,在任何时刻,算法都能对它已经读入的数据给出子序列问题的正确答案(其他算法不具有这个特性)。
* 具有这种特性的算法叫做 联机算法。
* 仅需要常量空间并以线性时间运行的联机算法几乎是完美的算法。
* 2.如果a[j]是负数,他不可能是最优序列的起点;任何负的子序列可能是最优子序列的前缀
* 3.如果 a[j] + a[j+1] 是负数,推进1。
* 4.这也叫在线算法, 指每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前解
*/
public static int maxSubSum(int[] a) {
int thisSum = 0, maxSum = 0;
for (int j =0 ; j < a.length; j++) {
thisSum += a[j];
if(thisSum < 0) {
thisSum = 0;
} else if(thisSum > maxSum) {
maxSum = thisSum;
}
}
return maxSum;
}
}
判断是否回文字符串
package com.jetta.pretty_data_structure;
/**
* @ClassName LeetCode9Palindrome
* @Description 判断是否回文字符串
* @Date 2023/4/16 22:19
* @Version V1.0
**/
public class LeetCode9Palindrome {
public boolean isPalindrome(String str) {
if(str.isEmpty() ) {
throw new IndexOutOfBoundsException();
}
if(str.length() < 2) {
return true;
}
char[] chars = str.toCharArray();
int right = chars.length / 2;
int left;
if(chars.length % 2 == 0) {
left = right-1;
}else {
left = right -1;
right = right +1;
}
int size = left;
for (int i = 0; i <= size; i++) {
if(chars[left] != chars[right]) {
return false;
}
right++;
left--;
}
return true;
}
/**
* 力扣题解
* 1.如果是负数则一定不是回文数,直接返回 false
* 2.如果是正数,则将其倒序数值计算出来,然后比较和原数值是否相等
* 3.如果是回文数则相等返回 true,如果不是则不相等 false
* 4.比如 123 的倒序 321,不相等;121 的倒序 121,相等
*/
class Solution {
public boolean isPalindrome(int x) {
if(x < 0)
return false;
int cur = 0;
int num = x;
while(num != 0) {
cur = cur * 10 + num % 10;
num /= 10;
}
return cur == x;
}
}
}