2023.3.27

15:两个链表相加

给定两个链表的头节点head1和head2,

认为从左到右是某个数字从低位到高位,返回相加之后的链表

例子 4 -> 3 -> 6 2 -> 5 -> 3

返回 6 -> 8 -> 9

解释 634 + 352 = 986

/*
* 两个链表相加
* 给定两个链表的头节点head1和head2,
认为从左到右是某个数字从低位到高位,返回相加之后的链表
例子     4 -> 3 -> 6        2 -> 5 -> 3
返回     6 -> 8 -> 9
解释     634 + 352 = 986
* */
public class AddTwoNumbers {
    public static class ListNode {
        public int val;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }

        public ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }

    /*
    * 思路:1:找到长链表L,短链表S
    * 2:划分成3个阶段,阶段1:长链表L,短链表S都有,阶段2:长链表L有,短链表S无,阶段3:长链表L无,短链表S无
    * 3:注意进位,不额外开辟空间,直接将相加的结果放到长链表L上。
    * */
    public static ListNode addTwoNumbers(ListNode head1, ListNode head2) {
        // 标注长短链表
        ListNode L = listLength(head1) > listLength(head2)  ? head1 : head2;
        ListNode S = L == head1 ? head2 : head1;
        // 标注当前链表的指向节点
        ListNode curL = L;
        ListNode curS = S;
        // 进位
        int carry = 0;
        // 当前长节点要填的数
        int curNuber = 0;
        // 一直记录着长链表的尾节点,用于连接第三阶段的节点
        ListNode last = L;
        // 第一阶段:长链表L,短链表S都有
        while(curS != null) {
            int curNum = curL.val + curS.val + carry;
            carry = curNum / 10;
            curNuber = curNum % 10;
            curL.val = curNuber;
            last = curL;
            curL = curL.next;
            curS = curS.next;
        }
        // 第二阶段:长链表L有,短链表S无
        while(curL != null) {
            int curNum = curL.val + carry;
            carry = curNum / 10;
            curNuber = curNum % 10;
            curL.val = curNuber;
            last = curL;
            curL = curL.next;
        }
        // 第三阶段
        if(carry == 1) {
            ListNode node = new ListNode(1);
            last.next = node;
        }
        return L;
    }


    // 计算链表的长度
    public static int listLength(ListNode head) {
        if (head == null) {
            return 0;
        }
        int count = 0;
        while(head != null) {
            count++;
            head = head.next;
        }
        return count;
    }
}

16:位图的实现

public class BitMap {
    private long[] bits;
    public BitMap(int max) {
        // max + 64 -> 当max == 63时,我们需要1个空间,当max == 0时我们需要1个空间
        bits = new long[(max + 64) >> 6];
    }

    public void add(int num) {
        /*
        // 属于哪个数组的下标
        int flg1 = num >> 6;
        // 属于当前数组下标下的哪个位置
        int flg2 = num & 63;
        bits[flg1] = (1L << flg2) | bits[flg1];
        */
        bits[num >> 6] |= (1L << (num & 63));
    }

    public void delete(int num) {
        /**
         * int flg1 = num >> 6;
         * int flg2 = num & 63;
         * bits[flg1] = bits[flg1] & ~(1L << flg2);
         */
        bits[num >> 6] &= ~(1L << (num & 63));
    }

    public boolean contains(int num) {
        return (bits[num >> 6] & (1L << (num & 63))) != 0;
    }
}

17:位运算实现加法

在这里插入图片描述

加法运算 -> 无进位相加的信息(异或运算) + 进位信息(与运算)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

a + b 可以不断的向下转化成无进位加信息+进位信息,但底层并没有加号这一说法(我们无法直接进行相加),所以我们需要一直往下进行转换直至进位信息是0的时候,我们得到的无进位加信息就是我们的答案。

// 用位运算实现 + - * /
public class BitAddMinusMultiDiv {

    public static int add(int a, int b) {
        int sum = a;
        while(b != 0) {
            sum = a ^ b; // 无进位相加信息
            b = (a & b) << 1; // 进位信心
            a = sum;
        }
        return sum;
    }
    
    // 判断是否是负数
    public static boolean isNeg(int n) {
        return n < 0;
    }

    // 取相反数
    public static int negNum(int n) {
        return add((~n),1);
    }
    // 减法就相当于:加一个相反数
    public static int minus(int a, int b) {
        return add(a,negNum(b));
    }
    // 乘法
    public static int multi(int a, int b) {
        int sum = 0;
        while(b != 0) {
            if((b & 1) != 0) {
                sum = add(sum , a);
            }
            b >>>= 1;
            a <<= 1;
        }
        return sum;
    }

    public static int div(int a, int b) {
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        // x / y
        int ans = 0;
        for (int i = 30; i >= 0; i--) {
            if((x >> i) >= y) {
                ans |= (1 << i);
                x = minus(x,y << i);
            }
        }
        return isNeg(a) != isNeg(b) ? negNum(ans) : ans;
    }

    public static int divide(int a, int b) {
        if(a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        }else if(b == Integer.MIN_VALUE) {
            return 0;
        }else if(a == Integer.MIN_VALUE) {
            if(b == negNum(1)) {
                return Integer.MAX_VALUE;
            }else {
                /*
                * c = (a + 1) / b
                * d = a - b * c
                * e = d / b
                * return e + c
                * */
                int c = div(add(a , 1), b);
                return add(c , div(minus(a,multi(b,c)),b));
            }
        }else {
            return div(a , b);
        }
    }
}

18:位运算实现乘法

在这里插入图片描述

 	public static int multi(int a, int b) {
        int sum = 0;
        while(b != 0) {
            if((b & 1) != 0) {
                sum = add(sum , a);
            }
            b >>>= 1;
            a <<= 1;
        }
        return sum;
    }

19:位运算实现除法

public static int div(int a, int b) {
        // 将负数全部转化成正数,这样好分析
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        // x / y
        int ans = 0;
        for (int i = 30; i >= 0; i--) {
            if((x >> i) >= y) {
                ans |= (1 << i);
                x = minus(x,y << i);
            }
        }
        return isNeg(a) != isNeg(b) ? negNum(ans) : ans;
    }

    public static int divide(int a, int b) {
        if(a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        }else if(b == Integer.MIN_VALUE) {
            return 0;
        }else if(a == Integer.MIN_VALUE) {
            if(b == negNum(1)) {
                return Integer.MAX_VALUE;
            }else {
                /*
                * c = (a + 1) / b
                * d = a - b * c
                * e = d / b
                * return e + c
                * */
                int c = div(add(a , 1), b);
                return add(c , div(minus(a,multi(b,c)),b));
            }
        }else {
            return div(a , b);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chen森柏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值