给你一个单链表的引用结点 head
。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的 十进制值 。
示例 1:
输入:head = [1,0,1]
输出:5
解释:二进制数 (101) 转化为十进制数 (5)
示例 2:
输入:head = [0]
输出:0
示例 3:
输入:head = [1]
输出:1
示例 4:
输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
输出:18880
示例 5:
输入:head = [0,0]
输出:0
提示:
- 链表不为空。
- 链表的结点总数不超过
30
。 - 每个结点的值不是
0
就是1
。
按权相加法算法
二进制 转 十进制 按权相加法 :sum = sum + value * 2
如何确定 n 的值?上图链表结点数量是 7,n 依次是 6,5,4,3,2,1,0
这个关系与数组长度和数组元素索引的关系非常相似
public int getDecimalValue(ListNode head) {
// 计算链表结点数量
int totalNum = 0;
ListNode cur = head;
while (cur != null) {
totalNum++;
cur = cur.next;
}
int sum = 0;
cur = head;
// 递减依次遍历链表
for (int i = totalNum; i > 0; i--) {
sum = sum + cur.val * (int)Math.pow(2, i-1);
cur = cur.next;
}
return sum;
}
复杂度分析
-
时间复杂度:O(N),其中 N 是给定链表的结点数目。
-
空间复杂度:O(1),只需要常数空间存放变量和指针即可。
按权相加法反向算法
十进制转二进制
18880 / 2 = 9440 余 0
9440 / 2 = 4720 余 0
4720 / 2 = 2360 余 0
2360 / 2 = 1180 余 0
1180 / 2 = 590 余 0
590 / 2 = 295 余 0
295 / 2 = 147 余 1
147 / 2 = 73 余 1
73 / 2 = 36 余 1
36 / 2 = 18 余 0
18 / 2 = 9 余 0
9 / 2 = 4 余 1
4 / 2 = 2 余 0
2 / 2 = 1 余 0
1 / 2 = 0 余 1
二进制:100100111000000
被除数 除以 除数 = 商 ...... 余数
反向
商 乘以 除数 + 余数 = 被除数
0 * 2 + 1 = 1
1 * 2 + 0 = 2
2 * 2 + 0 = 4
4 * 2 + 1 = 9
9 * 2 + 0 = 18
18 * 2 + 0 = 36
36 * 2 + 0 = 73
73 * 2 + 1 = 147
147 * 2 + 1 = 295
295 * 2 + 0 = 590
590 * 2 + 0 = 1180
1180 * 2 + 0 = 2360
2360 * 2 + 0 = 4720
4720 * 2 + 0 = 9440
9440 * 2 + 0 = 18880
public int getDecimalValue(ListNode head) {
int res = 0;
while(head != null){
res = res * 2 + head.val;
head = head.next;
}
return res;
}
复杂度分析
-
时间复杂度:O(N),其中 N 是给定链表的结点数目。
-
空间复杂度:O(1),只需要常数空间存放变量和指针即可。
位运算
乘2等于直接左移1位
public int getDecimalValue(ListNode head) {
int res = 0;
while(head != null){
res = (res << 1) + head.val;
head = head.next;
}
return res;
}
复杂度分析
-
时间复杂度:O(N),其中 N 是给定链表的结点数目。
-
空间复杂度:O(1),只需要常数空间存放变量和指针即可。