算法记录 一

1.java 稀疏算法
eg:五子棋
思想:将棋盘定义为横列两个数组intB[],intA[],里面保存的是棋盘的初始化
然后将棋盘落子记录下来存储在二位数组int[][],并且赋值 1/2代表黑子/白字

2.数组 求在该数组当中的第二大数字
思想:定义两个int 来代表max.max2. 循环数组 ,max 和 array[i] 做比较,遇到比自己大的,将值赋予max2,然后max此时等于array[i],并在此时比较array[i] 和 max2值大小
代码逻辑:

   int max,max2;
        if (array.length < 2 ){
            return array[0];
        }
        max = max2 = 0; /* 未考虑负数,如果考虑,那么max,max2的初始值为 2.-31次 */
        for (int value : array) {
            if (value > max) {
                max2 = max;
                max = value;
            }
            if (value < max && value > max2) {
                max2 = value;
            }
        }
        return max2;

3.给定一个数字,从数组中找两个数字相加等于目标和,输出这两个数字
方法1:暴力for循环

 rivate static int sumA(int[] array,int sum){
        int a,b;
        for (int i = 0; i <array.length;i++){
            a = array[i];
            for (int j = i+1; j < array.length; j++){
                b = array[j];
                if (a + b == sum){
                    System.out.println(a);
                    System.out.println(b);
                }
            }
        }
        return sum;
    }

方法2:使用hash,并且只需要判断此时是否containsKey(sum-array[i]) 并且此时的value 和 i 不一致,一致说明是只有一个数

  private static int[] sumB(int[] array, int sum) {
        Map<Integer, Integer> map = new HashMap<>();
        //将所有数组转为map.key为值,value为下标
        for (int i : array) {
            map.put(array[i], i);
        }
        for (int i = 0; i < array.length; i++) {
            int sub = sum - array[i];
            if (map.containsKey(sub) && map.get(sub) != i) {
                return new int[]{i, map.get(sub)};
            }
        }
        return null;
    }

4: 两个链表表示的数相加,这样就可以实现两个很⼤的数相加了,⽆需考虑数值 int ,float ,long的限制
思路:由个位进行运算 ,循环列表,直至 两个列表都为null时计算完毕,carry表示进位(最大也为1,因为 99 +99 < 200)
在这里插入图片描述
代码:/**

  • 两个链表表示的数相加,这样就可以实现两个很⼤的数相加了,⽆需考虑数值 int ,float 的限制
    ` */
public class listSum {
    /**
     * eg Input:(2->4->3) + (1->4->7)
     * output 3->9->0
     * 243 + 147 = 390
     * 思想 由个位进行运算 ,循环列表,直至 两个列表都为null时计算完毕
     * 方法2:for循环两个链表
     */
    static class listArray {
        int val;
        listArray next;
        listArray(int x) {
            val = x;
        }

  public static listArray twoNumberAdd(listArray a, listArray b) {
        //初始化节点头
        listArray dummyHead = new listArray(0);
        //链表a的头p->个位数字
        listArray p = a;
        //链表b的头p->个位数字
        listArray q = b;
        //从节点第一位开始运算 也就是个位数
        listArray curr = dummyHead;
        //进位,默认是0 不进位
        int carry = 0;
        while (p != null || q != null){
            int x = (p != null) ? p.val : 0;
            int y = (q != null) ? q.val : 0;
            //判断是否要进位
            int sum = carry + x + y;
            //进位永远是1
            carry = sum / 10;
            //节点头移动判断
            curr.next = new listArray(sum % 10);
            //节点头更新
            curr = curr.next;
            if (p != null) {
                //下一位运算,替换值
                p = p.next;
            }
            if (q != null) {
                //下一位运算,替换值
                q = q.next;
            }
        }
        if (carry > 0){
            //更新链表
            curr.next = new listArray(carry);
        }
        return dummyHead.next;
    }`

5.给定⼀个字符串,找到没有重复字符的最⻓⼦串,返回它的⻓度
思路:简单粗暴 两个循环 加一个 条件判断

/**
 * 给定⼀个字符串,找到没有重复字符的最⻓⼦串,返回它的⻓度
 */
public class findLongString {

    /**
     * 思路1:简单粗暴 两个循环穷举所有⼦串,然后再⽤⼀个函数判断该⼦串中有没有重复的字符
     * set 天然不重复
     */

    private static int lengthOfSubstring(String  s){
        int suffice = 0;
        for (int i = 0; i < s.length();i++){
            for (int j = i + 1; j <= s.length(); j++){
                if (repeat(s,i,j)){
                    suffice = Math.max(suffice, j - i);
                }
            }
        }

        System.out.println(suffice);
        return 0;
    }
    private static boolean repeat(String s, int start, int end){
        Set<Character> set = new HashSet<>();
        for(int i = start; i < end; i++){
            Character charAt = s.charAt(i);
            if (set.contains(charAt)){
                return false;
            }
            set.add(charAt);
        }
        return true;
    }

    public static void main(String[] args) {
        String a = "asnfuanfdinfgapndsomdaihggrngaosdjsopmopdgjsd";
        lengthOfSubstring(a);
    }
}
方法二:滑动窗口算法可以优化掉很多不需要再判断的字符串
     * 优化思想: 比如 string[0,8) 之前没有重复,按照思路1 接下来就要判断 string[0,9)有没有重复,而此时又多了一次string[0,8)无效循环
     * 那我 我们只需要判断string[9] 是否在string[0,8)中即可,不在的话,就表明 str[0,9) 中没有重复的字符。 如果在的后,那么后续的string[0,xx)也不用再判断了,
     * 那么从String[1,xx)在开始判断
     
   private static int method2(String s){
        Set<Character> set = new HashSet<>();
        int suffice = 0;
        int i = 0;
        int j = 0;
        while (i < s.length() && j < s.length()){
            if (!set.contains(s.charAt(j))){
                set.add(s.charAt(j++));
                suffice = Math.max(suffice , j - i);
            }else {
                set.remove(s.charAt(i++));
            }
        }
        return suffice;
    }
方法三:
    /**
     * 思路3  将set 转用 map存储,此时可以直接不考虑之前不满足的情况,而无需 在让i++ ,j++ 正在进行循环判断
     */
    private static int method3(String s){
        //k-> 字符串  v-> 下标
        Map<Character, Integer> map = new HashMap<>();
        int suffice = 0;
        for (int j = 0, i = 0; j < s.length(); j++){
            //判断map是否包含后一位的下标value ->不包含的话,map 继续 put(k,v)  包含的话,对map的 key 进行 value 替换,并且对i 进行 跳跃到j的后一位,j之前100%是重复,所以直接不考虑
            if (map.containsKey(s.charAt(j))){
                 i = Math.max(map.get(s.charAt(j)), i);
            }
            suffice = Math.max(suffice, j - i +1);
            // j + 1 代表 stirng 下标 i 移动的位置 即 i 跳跃 直接不考虑 j 前方的所有字符串
            map.put(s.charAt(j),j + 1);
        }
        return suffice;
    }

6:已知两个有序数组,找到两个数组合并后的中位数

 /**
     * 方法一:两个数组合并为一个新的数组并且在排序,在求中位数
     */

    private static long findMiddleNumber(int[] A, int[] B){
        int[] nums = new int[A.length + B.length];
        for (int i = 0; i < nums.length; i++){
            if (i < A.length){
                nums[i] = A[i];
            } else {
                nums[i] = B[i - A.length];
            }
        }
        //新数组排序
        Arrays.sort(nums);
        // 偶数
        if (nums.length % 2 == 0){
            return (nums[nums.length / 2 -1] + nums[nums.length / 2]) / 2;
        }else{
          //奇数
            return nums[(nums.length + 1) /2];
        }
      
    }

7:回文字符串 : 回文字符串并输出最长的回文字符串/或者长度

/**
     * 方法一: 从中折叠, 循环判断 从中折叠 前一位 和 后一位 是否 相等
     */
    private static boolean isPalindrome(String words) {
        for (int i = 0; i < words.length() / 2; i++) {
            if (words.charAt(i) != words.charAt(words.length() - i - 1)) {
                return false;
            }
        }
        return true;
    }

    private static  String findBestLongWords(String words) {
        int w = words.length();
        int maxLong = 0;
        //需要一个初始化字符串来记录回文字符串
        String s = "";
        for (int i = 0; i < w; i++) {
            for (int j = i + 1; j <= w; j++) {
                String pd = words.substring(i,j);
                if (isPalindrome(pd) && pd.length() > maxLong){
                    maxLong = Math.max(maxLong, pd.length());
                    s = pd;
                }
            }
        }
        return s;
    }    

8:给定一个字符串,按照竖着的Z方式排列字符
在这里插入图片描述

/**
     * 按照写Z的过程 正常循环写,然后便利到两端的话就改变方向
     * numRows 为input s为input
     */

    private static String Z(String s, int numRows) {

        if (numRows == 1) {
            return s;
        }
        //rows 指需要build的行数
        List<StringBuilder> rows = new ArrayList<>();
        //避免最后出现越界->取较小值
        for (int i = 0; i < Math.min(numRows, s.length()); i++) {
            rows.add(new StringBuilder());
        }
        int curRow = 0;
        //代表当前方向
        boolean goingDown = false;

        for (char c : s.toCharArray()) {
            //行数拼接字符串
            rows.get(curRow).append(c);
            //转向
            if (curRow == 0 || curRow == numRows - 1) {
                goingDown = !goingDown;
            }
            //控制方向 1 向下 -1 向上
            curRow += goingDown ? 1 : -1;
        }
        StringBuilder builder = new StringBuilder();
        for (StringBuilder row : rows) {
            builder.append(row);
        }
        System.out.println(builder.toString());
        return builder.toString();
    }

    public static void main(String[] args) {
        String s = "sdertfdvsads";
        Z(s,5);
        zTwo(s,5);
    }

    /**
     * 思路二 查找规律 周期性为 2 * numRows -2 ,然后在开启重复相同路径
     * 第一行的规律就是 下标 0
     * 第二行的规律就是  下标1 第二个下标就是下一个周期的0下标 - 当前下标 eg  第二行  下标1,下标(2 * numRows -2 ) - 1
     * 第三行的规律就是 下标2 第二个下标就是下一个周期的0下标 - 当前下标 eg  第二行  下标1,下标(2 * numRows -2 ) - 2
     * 一次类推 ,而且 2 * numRows -2 。length 为一个周期,下个周期循环 之前的规律,只需要在 下个规律的周期下标 + 2 * numRows -2即可
     */

    private static String zTwo(String s, int numRows){
        if (numRows == 1){
            return s;
        }

        StringBuilder builder = new StringBuilder();
        int size = s.length();
        int guilv = 2 * numRows - 2;
        //i 代表 第几行 从第一行下标0开始计算,第一行全部完毕 第二行
        for (int i = 0; i < numRows; i++){
            //每次增加一个周期
            for (int j = 0; j + i < size; j += guilv){
                builder.append(s.charAt( j + i));
                //不等于0行和最后一行
                if (i != 0 && i != numRows -1 && j + guilv - i < size){
                    builder.append(s.charAt(j + guilv - i));
                }
            }
        }
        return builder.toString();
    }

9:输入它的整数,输出它的倒置
eg i:123 o:321 ; -123 -321 250 52

 private static int invert(int num){
        long result = 0;
        while (num != 0){
            //取余
            int top = num % 10;
            //每次缩小10倍
            num = num / 10;
            //倒置为第一位
            result = result * 10 + top;
        }
        //判断是否溢出
        if ( result > Integer.MAX_VALUE || result < Integer.MIN_VALUE){
            return 0;
        }
        System.out.println((int) result);
        return (int) result;
    }

    public static void main(String[] args) {
        int a = 1215487;
        invert(a);
    }

10:判断是不是回文数,负数不是回文数
eg 121 tue -121 false 10 false 101 ture

  /**
     * 思路一
     * int 转 string 然后判断 是不是回文串
     */

    private boolean huiwen(int num){
        //首先判断int 是否 为负数  超过范围 自动false
        if (num < 0){
            return false;
        }
        String number = String.valueOf(num);
        for (int i = 0; i < number.length() / 2; i++) {
            if (number.charAt(i) != number.charAt(number.length() - i - 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 思路二
     * 假设存在这么⼀个数,倒置后是超出 int 范围的,并且它是回⽂数字
     * int 最⼤为 2147483647
     * 有没有可能是最⾼位⼤于 2 导致的溢出,⽐如最⾼位是 3 ,因为是回⽂串,所以最低位是 3 ,这就将导致
     * 转置前最⾼位也会是 3 ,所以不可能是这种情况
     * 有没有可能是第 2 ⾼位⼤于 1 导致的溢出,此时保持最⾼位不变,假如第 2 ⾼位是 2,因为是回⽂串,所
     * 以个位是 2,⼗位是 2 ,同样的会导致倒置前超出了 int 的最⼤值,所以也不可能是这种情况
     * 同理,第 3 ⾼位,第 4,第 5,直线左边的都是上述的情况,所以不可能是前边的位数过⼤
     * 为了保证这个数是溢出的,前边 5 位必须固定不变了,因为它是回⽂串,所以直线后的灰⾊数字就⼀定是 4
     * ⽽此时不管后边的数字取多少,都不可能是溢出的了
     */
    private boolean huiwenTwo(int num){
        if (num < 0){
            return false;
        }
        long result = 0;
        //倒置num
        while (num != 0){
            //取余
            int top = num % 10;
            //每次缩小10倍
            num = num / 10;
            //倒置为第一位
            result = result * 10 + top;
        }
        //判断 num 与 倒置 是否一致
        return num == result;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值