B站链接
一、链表反转(206)
解法一:迭代
需要有三个变量分别来存储上一个元素的指针,当前元素的指针以及下一个元素的指针。
以第一次反转为例,
第一步:先把当前元素的下一个元素指针存到next,这步只单纯为了备份当前的下一元素,
即使第二步对curr.next进行修改也无妨,第四步就可以用到该备份的值。
第二步:把当前元素的的下一个元素指针置为上一个元素的指针,
第三步:把当前元素赋为上一元素。
第四步:获得第一步备份值,使当前元素为其备份值。
public ListNode reverseList(ListNode head) {
ListNode pre = null,next;
ListNode curr = head;
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while(curr!=null){
next = curr.next;//临时节点,暂存当前节点的下一节点,用于后移
curr.next = pre;//将当前节点指向它前面的节点
pre = curr;//前指针后移
curr = next;//当前指针后移
}
return pre;
}
解法二:递归
重在理解 head.next.next = head;
head.next=null;
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
二、素数统计
解法一:暴力统计
public static void main(String[] args) {
System.out.println(bf(100));//25
}
public static int bf(int n){
int count = 0;
for(int i = 2 ;i<n;i++){
count += isPrime(i)?1:0;
}
return count;
}
private static boolean isPrime(int x) {
for(int i =2;i*i<=x;i++){
if(x%i==0) {
return false;
}
}
return true;
}
解法二:埃筛法
public static int eratosthenes(int n){
int[] is_Prime = new int[10000];
int[] prime = new int[100000];
for(int i =2;i<is_Prime.length;i++){
is_Prime[i] = 1;//先假设全为素数
}
int count = 0;
for(int i = 2;i <= n; i++){
if (is_Prime[i] == 1){
prime[count++] = i;
for(int j = 2*i;j <= n; j += i){
is_Prime[j] = 0;
}
}
}
return count;
}
解法三:欧氏筛
public static int eratosthenes(int n){
int len=0;
for(int i=0;i<=n;i++){
flag[i]=0;//flag为0说明未被筛出;为1说明已经被筛出;
}
flag[0]=flag[1]=1;//0,1不是素数,直接筛出去;
for(int i=2;i<=n;i++){
if(flag[i]==0){//如果当前最前面的未被筛出说明是素数,入表。
prime[len++]=i;
}
for(int j=0;prime[j]*i<=n;j++){
flag[prime[j]*i]=1;//标记为非素数
if(i%prime[j]==0)break;//仔细想明白此处为何是i%prime[j]==0就break!
}
}
return len;
}
在埃筛法可能会出现重复标记的情况,而欧氏筛解决了该情况。
三、三个数的最大乘积(628)
解法一:
public int maximumProduct(int[] nums) {
Arrays.sort(nums);
int n = nums.length;