# 234 palindrome linked list

Method 1: speed pointer + reverse linked list

This O1 is so hard. Set the function to reverse the linked list, and then set the fast and slow pointer to find half of the nodes in the linked list (the fast pointer is always one step faster than the slow pointer, so when the fast pointer comes to the end, the slow pointer is just at half of the linked list). Reverse the latter half of the list to check the first half of the list = = the second half of the list.

class Solution: def isPalindrome(self, head: ListNode) -> bool: first_half_end = self.end_of_first_half(head) second_half_start = self.reverseList(first_half_end.next) first_position = head second_position = second_half_start while second_position: if first_position.val != second_position.val: return False first_position = first_position.next second_position = second_position.next return True def reverseList(self, head: ListNode) -> ListNode: if not head or not head.next: return head cur = self.reverseList(head.next) head.next.next = head head.next = None return cur def end_of_first_half(self, head): fast = slow = head while fast.next and fast.next.next: fast = fast.next.next slow = slow.next return slow

Method 2: traverse the linked list

class Solution: def isPalindrome(self, head: ListNode) -> bool: vals, node = [], head while node: vals.append(node.val) node = node.next return vals == vals[::-1]

# 264 ugly numbers

#For example, 1, 2 and 3 now have three ugly numbers, and the next ugly number 4 uses the product of 2, so the subscript + 1,

#For factor 2: 2 is no longer used as the basic multiplier.

#1,2,3,4 now there are 4 ugly numbers, and the next ugly number 5 uses the 5 product subscript + 1,

#For factor 5, 1 is no longer used as the basic multiplier.

#That is, start to consider the multiplier after 1 as the basic multiplier. This is the meaning of subscript + 1. After using this factor, throw away the previous multiplier for this factor

The idea of dynamic programming is very good..

class Solution: def nthUglyNumber(self, n: int) -> int: dp = [1] * n index5 = index2 = index3 = 0 for i in range(1, n): dp[i] = min(dp[index2]*2, dp[index3]*3, dp[index5]*5) if dp[i] == 2 * dp[index2]: index2 += 1 if dp[i] == 3 * dp[index3]: index3 += 1 if dp[i] == 5 * dp[index5]: index5 += 1 return dp[n-1]

# 338 question bit count

We can only think of the conventional solution of O(nlogn) time complexity, traverse each i and count 1 bits for each i. The official answered three DPS to me.. We should study it carefully. In addition, in the conventional solution, if the ans array is set to traverse, the time will be one bit longer than that of writing the function call function

## DP 1: most significant bit

For 0 < = J < I, there is always bits{i} = bits{j} + 1. Find the conditions and laws to do dp

For the power y of 2, only the highest bit of Y is 1, that is, one bit of Y is 1

For 0 < = y < x, X is z larger than y, then one bit of X is obviously 1 more than one bit of z, that is, bits{x} = bits{z} + 1

Explanation: because the 1 of Y is in the highest bit, and the value z of x is larger than y, the binary expression singled out is exactly the same as the last few bits of x, so one bit of x is only the 1 with the highest bit more than one bit of z

When the next power of 2 is encountered, the most significant digit is updated.

class Solution: def countBits(self, n: int) -> List[int]: ans = [0] * (n+1) for i in range(1, n+1): if (i & i-1) == 0: highbits = i ans[i] = ans[i-highbits] + 1 return ans

## DP 2: least significant bit

I don't think it's easy to understand that it's called the least significant bit. Its idea is actually simple. It's better to use the method of naming and descending times

For any number x, shift it to the right by one bit, that is, discard the lowest bit, then bits{x} = bits{x/2} + a

When the lowest bit discarded is 1, then a=1, otherwise 0

The operation of x/2 is to reduce the original power, because one bit less binary is to reduce the power of 1.

class Solution: def countBits(self, n: int) -> List[int]: ans = [0] * (n+1) for i in range(n+1): ans[i] = ans[i>>1] + (i&1) #Here, I > > 1 has the same effect as i//2, which is slightly slower return ans #Using append without declaring array space in advance is also slightly slower

## DP 3: lowest setting bit

I & I-1 is still used as Kung Fu. This operation will delete the last 1

That is, for y, x = y & Y-1, bits {y} = bits {x}+ one

class Solution: def countBits(self, n: int) -> List[int]: ans = [0] * (n+1) for i in range(1, n+1): ans[i] = ans[i&i-1] + 1 return ans

Bit operation is really broad and profound!!!! Sure enough, it is the most basic of computer