简单算法杂章

折半查找

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;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值