leetcode刷题记录(最新推荐)

 更新时间:2024年12月07日 11:22:05   作者:阿伟*rui  
本文给大家分享的leetcode刷题记录包括矩阵置0、螺旋矩阵、旋转图像、搜索二维矩阵、反转链表、回文链表,每道题目提供了解答方法和思路,感兴趣的朋友跟随小编一起看看吧

day4 73:矩阵置0

题目:

我的答案:

ArrayList<Integer> x = new ArrayList<>();
ArrayList<Integer> y = new ArrayList<>();
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        if (matrix[i][j]==0){
            x.add(i);
            y.add(j);
        }
    }
}
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        if (x.contains(i)||y.contains(j)){
            matrix[i][j]=0;
        }
    }
}

使用集合记录哪一行哪一列含有0,记录下只后,再次遍历矩阵,只要这一行出现0,那么全部就是0,列也是;

题解:

int m=matrix.length;
int n =matrix[0].length;
boolean x=false;boolean y =false;
for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
        if (matrix[i][0]==0){
            y=true;
        }
    }
}
for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
        if (matrix[0][j]==0){
            x=true;
        }
    }
}
for (int i = 1; i < m; i++) {
    for (int j = 1; j < n; j++) {
        if (matrix[i][j]==0){
            matrix[i][0]=matrix[0][j]=0;
        }
    }
}
for (int i = 1; i < m; i++) {
    for (int j = 1; j < n; j++) {
        if (matrix[i][0]==0||matrix[0][j]==0){
            matrix[i][j]=0;
        }
    }
}
if (x){
    for (int i = 0; i < n; i++) {
        matrix[0][i]=0;
    }
}
if (y){
    for (int i = 0; i < m; i++) {
        matrix[i][0]=0;
    }
}

题解不再使用额外的数据结构,而是使用变量来标记,这里的主要思路是,利用第一行和第一列来记该行和该列有没有0,因为第一行和第一列被用作标记,所以我们要先记录下来,第一行和第一列有没有0,通过两个循环记录下来,然后遍历整个矩阵,如果一个位置是0,那么这个位置所在行的第一行,和第一列标为0;然后再通过一个循环,如果遍历的位置的第一行或第一列为0那么该位置也为0;然后对第一行和第一列进行处理,如果标记的为0那么第一行或者第一列全部为0;

54:螺旋矩阵

答案:

int left=0;
    int right= matrix[0].length-1;
    int top=0;
    int bottom= matrix.length-1;
    ArrayList<Integer> res = new ArrayList<>();
    while (left<=right&&top<=bottom){
        for (int i = left; i <= right; i++) {
            res.add(matrix[top][i]);
        }
        top++;
        for (int j = top; j <=bottom ; j++) {
            res.add(matrix[j][right]);
        }
        right--;
        if (top<=bottom){
        for (int i = right; i >=left ; i--) {
            res.add(matrix[bottom][i]);
        } bottom--;
        }
        if (left<=right){
        for (int j = bottom; j >=top ; j--) {
                res.add(matrix[j][left]);
        }
            left++;}
    }
    return res;
}
从左到右,顶部一层遍历完往下移一位,top++;从上到下,遍历完右侧往左移一位,right–;从右到左,判断top <= bottom,即是否上下都走完了。遍历完底部上移,bottom–;从下到上,判断left <= right,遍历完左侧右移,left++;

48-旋转图像

题目要求不能创建新的矩阵。我们先来使用一个矩阵来模拟一下过程:

 int[][]copy=new int[n][n];
 for (int i = 0; i < n; i++) {
     for (int j = 0; j < n; j++) {
         copy[j][n-i-1]=matrix[i][j];
     }
 }
 for (int i = 0; i < n; i++) {
     for (int j = 0; j < n; j++) {
         matrix[i][j]=copy[i][j];
     }
 }

具体的规律就是第一行的元素都跑到最后一列按顺序从上到下排序,我们可以找到坐标的规律;

摸索到坐标之间的规律后,我们就要考虑实现题目中的使用原始的矩阵进行旋转;

进行旋转其实是四个元素进行交换位置,就比如四个边角,就是顺时针的交换位置,我们可以总结一下,四个边角坐标之间的关系,然后进行交换位置,需要注意的是需要交换位置的元素有哪些,因为一下就是4个元素,我们需要进行筛选,根据每一行来看,不论奇数还是偶数,只要旋转n/2的行数。根据每一列来看,如果是偶数比如说4列,那么我们只需要旋转前面两列就行,如果是奇数,比如说是5,那么除了1,2列还有第三列要单独处理,所以说要3列也就是n+1/2;

所以:

int n = matrix.length;
for (int i = 0; i < n / 2; i++) {
    for (int j = 0; j < (n + 1) / 2; j++) {
        int temp=matrix[i][j];
        matrix[i][j]=matrix[n-j-1][i];
        matrix[n-j-1][i]=matrix[n-i-1][n-j-j];
        matrix[n-i-1][n-j-j]=matrix[j][n-i-1];
        matrix[j][n-i-1]=temp;
    }
}

然后就是第三种方法,第三种方法使用交换,旋转90度我们可以找到规律就是先是上下翻转,然后是按照对角线进行反转:

int n = matrix.length;
for (int i = 0; i < n / 2; i++) {
    for (int j = 0; j < n; j++) {
        int temp=matrix[i][j];
        matrix[i][j]=matrix[n-i-1][j];
        matrix[n-i-1][j]=temp;
    }
}
for (int i = 0; i < n; i++) {
    for (int j = 0; j < i; j++) {
        int temp=matrix[i][j];
        matrix[i][j]=matrix[j][i];
        matrix[j][i]=temp;
    }
}

24-搜索二维矩阵||

题目:

答案:

这题直接遍历搜索也能过;

然后可以优化,比如适用二分查找对每一行数据进行查找;

for (int[] ints : matrix) {
    int index = search(ints,target);
    if (index>=0){
        return true;
    }
}
return false;
public static int search(int[]matrix,int target){
    int left=0;
    int right=matrix.length;
    while (left<=right){
        int mid=(right-left)/2+left;
        if (matrix[mid]==target){
            return mid;
        }
        if (matrix[mid]>target){
            right=mid-1;
        }else {
            left=mid+1;
        }
    }
    return -1;
}

然后还可以从右上角开始检索:

int m =0;
int n =matrix[0].length-1;
while (n>=0&&m<matrix.length){
    if (matrix[m][n]==target){
        return true;
    }
    if (matrix[m][n]>target){
        n--;
    }else {
        m++;
    }
}
return false;

从右上角开始,如果当前值小于目标值就向下遍历,因为下面的大,如果大于目标值就像左移。有点类似于二叉搜索树,左边是左子树,下面是右子树;

206-反转链表

第一种:迭代:

ListNode pre=null;
  ListNode cur=head;
  while (cur!=null){
      ListNode temp=cur.next;
      cur.next=pre;
      pre=cur;
      cur=temp;
  }
  return pre;

这里需要使用虚拟头节点:

这里先用中间变量记录cur。next,然后反转指针,将指针指向前面的节点。

然后再使pre=cur;

cur=temp

第二种:递归:

if (head==null||head.next==null){
    return head;
}
ListNode node = reverseList(head.next);
node.next.next=node;
node.next=null;
return node;

234:回文链表

题目:

第一种:双指针:

List<Integer>res=new ArrayList<>();
 while (head!=null){
     res.add(head.val);
     head=head.next;
 }
 int l =0;
 int r=res.size()-1;
 while (l<r){
     if (res.get(l)!=res.get(r)){
         return false;
     }
     l++;
     r--;
 }
 return true;

先将整个链表的数据加入到集合中,然后再利用双指针进行判断是否是回文子串;

第二种:

cur=head;
return reserve(head);
public boolean reserve(ListNode node){
    if (node!=null){
        if (!reserve(node.next)){
            return false;
        }
        if (cur.val!=node.val){
            return false;
        }
        cur=cur.next;
    }
    return true;
}

将链表放到外部,然后在函数内部递归,使指针遍历到链表的末尾,然后再拿外部的链表和内部的链表末尾进行比较;

141-环形链表

解法1:使用集合判断是否相同:

 HashSet<ListNode> nodes = new HashSet<>();
 ListNode cur=head;
 while (cur!=null){
     if (!nodes.contains(cur)){
         nodes.add(cur);
     }else {
         return true;
     }
     cur=cur.next;
 }
 return false;

就是一直遍历,一边遍历,一边将链表的元素加入到集合中,如果发现加入的元素在集合中已经存在了那么就可以说明这是一个环形链表,于是就返回true。如果一直都没有重复的,遍历结束就会返回false

解法2:使用快慢指针,快的走2格,慢的走一格,总会相遇的:

ListNode fast=head;
ListNode slow=head;
while (fast!=null&&fast.next!=null){
    fast=fast.next.next;
    slow=slow.next;
    if (fast==slow){
        return true;
    }
}
return false;

就是快慢指针,如果快指针和慢指针是一个元素说明是环形链表;为什么一定相遇呢:这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

142-环形链表||:

题目:

答案1:

通过集合:

HashSet<ListNode> nodes = new HashSet<>();
ListNode cur = head;
while (cur != null) {
    if (!nodes.contains(cur)) {
        nodes.add(cur);
    }else {
        return cur;
    }
    cur=cur.next;
}
return null;

当出现重复的元素时就直接返回就行,返回的就是环形的入口元素;

答案2:快慢指针:

ListNode fast=head;
ListNode slow=head;
while (fast!=null&&fast.next!=null){
    fast=fast.next.next;
    slow=slow.next;
    if (fast==slow){
        break;
    }
}
if (fast==slow){
    fast=head;
    while (fast!=slow){
        fast=fast.next;
        slow=slow.next;
    }
    return fast;
}
return null;

在快慢指针重合之后:

我们来讨论一下:f是快指针走的路程。s是慢指针走的路程;

f=s+nb。f=2s。----》s=nb。然后到洞口走的路程的可能是:a+nb;a是环口与链表首部的距离;

相遇的时候s=nb,如果s走a步就是s+nb,正好到环口;

此时我们将快指针放在链表的首部,也走a步也会走到环口,所以当将快指针放到环口时只要快慢指针相遇就是环口的位置;

02-两数相加

题目:

答案:

ListNode sentry = new ListNode(0);
ListNode cur = sentry;
int carry = 0;
while (l1 != null || l2 != null || carry != 0) {
    int num1 = l1 != null ? l1.val : 0;
    int num2 = l2 != null ? l2.val : 0;
    int sum=num1+num2+carry;
    carry=sum/10;
    ListNode newNode=new ListNode(sum%10);
    cur.next=newNode;
    cur=newNode;
    if (l1!=null)l1=l1.next;
    if (l2!=null)l2=l2.next;
}
return sentry.next;

由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。

我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2,进位值为 carry,则它们的和为 n1+n2+carry;其中,答案链表处相应位置的数字为 (n1+n2+carry)mod10,而新的进位值为 ⌊
10
n1+n2+carry

⌋。

如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。

此外,如果链表遍历结束后,有 carry>0,还需要在答案链表的后面附加一个节点,节点的值为 carry。

19-删除链表中第n个元素:

题目:

ListNode fast=head;
for (int i = 0; i < n; i++) {
    fast=fast.next;
}
ListNode head1=new ListNode(0);
head1.next=head;
ListNode slow=head1;
while (fast!=null){
    fast=fast.next;
    slow=slow.next;
}
slow.next=slow.next.next;
return head1.next;

24-两两交换链表的元素

题目:

if (head==null||head.next==null){
    return head;
}
ListNode head0=new ListNode(0);
ListNode pre=head0;
pre.next=head;
ListNode cur=head;
while (cur.next!=null){
    pre.next=cur.next;
    pre=cur;
  cur=cur.next;
   pre.next=cur.next;
   cur.next=pre;
   pre=cur;
   cur=cur.next;
}
return head0.next;

到此这篇关于leetcode刷题记录(最新推荐)的文章就介绍到这了,更多相关leetcode刷题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ChatGPT体验辅助写代码功能实测(附编程测试)

    ChatGPT体验辅助写代码功能实测(附编程测试)

    ChatGPT最近霸屏了,咱们也来玩玩,下面这篇文章主要给大家介绍使用ChatGPT辅助写代码的体验,需要的朋友可以参考下
    2023-02-02
  • 解决VIM显示utf-8文件乱码问题

    解决VIM显示utf-8文件乱码问题

    在Vim中,有四个与编码有关的选项,它们是:fileencodings、fileencoding、encoding和termencoding。下面,我们详细介绍一下这四个选项的含义和作用,感兴趣的朋友一起看看吧
    2020-02-02
  • Prometheus + Grafana 构建强大的监控和数据可视化系统(最新推荐)

    Prometheus + Grafana 构建强大的监控和数据可视化系统(最新推荐)

    Prometheus 是一个时间序列数据库,但是,它不仅仅是一个时间序列数据库,它涵盖了可以绑定的整个生态系统工具集及其功能,非常适合Kubernetes集群的监控,这篇文章主要介绍了Prometheus + Grafana 构建强大的监控和数据可视化系统,需要的朋友可以参考下
    2024-05-05
  • vscode输入npm install报错:node-sass@8.0.0 install:'node scripts/install.js'解决

    vscode输入npm install报错:node-sass@8.0.0 install:'node 

    这篇文章主要给大家介绍了关于vscode输入npm install报错:node-sass@8.0.0 install:'node scripts/install.js'的解决方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Protobuf在Cmake中的正确使用方法详解

    Protobuf在Cmake中的正确使用方法详解

    这篇文章主要介绍了Protobuf在Cmake中的正确使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 联邦学习论文解读分散数据的深层网络通信

    联邦学习论文解读分散数据的深层网络通信

    这篇文章主要为大家介绍了论文解读分散数据的深层网络通信有效学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Elasticsearches打分机制讲解

    Elasticsearches打分机制讲解

    这篇文章主要介绍了Elasticsearches打分机制解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • 一文弄懂字符集编码

    一文弄懂字符集编码

    软件开发人员经常遇到中文乱码、软件不能显示中文等类似问题,本文主要介绍了一文弄懂字符集编码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 编程知识点(1)关键词之存储类型

    编程知识点(1)关键词之存储类型

    这篇文章主要介绍了编程知识点(1)关键词之存储类型的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-07-07
  • 支付宝小程序向用户发红包的实现方法

    支付宝小程序向用户发红包的实现方法

    这篇文章主要介绍了支付宝小程序向用户发红包的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11

最新评论