剑指offer(51-60)题解(一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 剑指offer(51-60)题解

51题解–构建乘积数组


题目描述


给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)

对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。


思路解析


因为该题无法运用除法,所以我们需要另外想办法,这里我们可以将整个乘积数组看成是以下两部分:


20200810195402996.png


这样分两个区间,两个循环就能解决问题


源代码


public class Solution {
public int[] multiply(int[] A) {
    int []B=new int [A.length];
    for(int i=0;i<B.length;i++)
    {
      int sum1=1;
      int sum2=1;
      for(int j=0;j<i;j++)
        sum1*=A[j];
      for(int j=i+1;j<B.length;j++)
        sum2*=A[j];
      B[i]=sum1*sum2;
    }
    return B;
    }
}


52题解–正则表达式匹配*****


题目描述


请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配


思路解析


这题是真的恶心,卡了我好久,关键最后还没A出来。看了别人的题解也是模模糊糊。

这里我就不讲解了,直接贴出大神的想法。评论区大家可以讨论讨论

当模式中的第二个字符不是“”时:

1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。

2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。

而当模式中的第二个字符是“”时:

如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:

1、模式后移2字符,相当于x被忽略;

2、字符串后移1字符,模式后移2字符;

3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为可以匹配多位;


源代码


public class Solution {
    public boolean match(char[] str, char[] pattern) {
    if (str == null || pattern == null) {
        return false;
    }
    int strIndex = 0;
    int patternIndex = 0;
    return matchCore(str, strIndex, pattern, patternIndex);
}
public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
    //有效性检验:str到尾,pattern到尾,匹配成功
    if (strIndex == str.length && patternIndex == pattern.length) {
        return true;
    }
    //pattern先到尾,匹配失败
    if (strIndex != str.length && patternIndex == pattern.length) {
        return false;
    }
    //模式第2个是*,且字符串第1个跟模式第1个匹配,分3种匹配模式;如不匹配,模式后移2位
    if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
        if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
            return matchCore(str, strIndex, pattern, patternIndex + 2)//模式后移2,视为x*匹配0个字符
                    || matchCore(str, strIndex + 1, pattern, patternIndex + 2)//视为模式匹配1个字符
                    || matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1个,再匹配str中的下一个
        } else {
            return matchCore(str, strIndex, pattern, patternIndex + 2);
        }
    }
    //模式第2个不是*,且字符串第1个跟模式第1个匹配,则都后移1位,否则直接返回false
    if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {
        return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
    }
    return false;
  }
} 


53题解–表示数值的字符串


题目描述


请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。


思路解析


字符串处理的问题,但是这题要考虑的店非常的多,处理起来也是比较的麻烦,主要注意以下的点。

设置三个标志符分别记录“+/-”、“e/E”和“.”是否出现过。

对于“+/-”: 正常来看它们第一次出现的话应该出现在字符串的第一个位置,如果它第一次出现在不是字符串首位,而且它的前面也不是“e/E”,那就不符合规则;如果是第二次出现,那么它就应该出现在“e/E”的后面,如果“+/-”的前面不是“e/E”,那也不符合规则。

对于“e/E”: 如果它的后面不接任何数字,就不符合规则;如果出现多个“e/E”也不符合规则。

对于“.”: 出现多个“.”是不符合规则的。还有“e/E”的字符串出现“.”也是不符合规则的。 同时,要保证其他字符均为 0-9 之间的数字。


源代码


public class Solution {
    public boolean isNumeric(char[] str) {
        int len = str.length;
        boolean sign = false, decimal = false, hasE = false;
        for(int i = 0; i < len; i++){
            if(str[i] == '+' || str[i] == '-'){
                if(!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E')
                    return false;
                if(sign && str[i-1] != 'e' && str[i-1] != 'E')
                    return false;
                sign = true;
            }else if(str[i] == 'e' || str[i] == 'E'){
                if(i == len - 1)
                    return false;
                if(hasE)
                    return false;
                hasE = true;
            }else if(str[i] == '.'){
                if(hasE || decimal)
                    return false;
                decimal = true;
            }else if(str[i] < '0' || str[i] > '9')
                return false;
        }
        return true;
    }
}


54题解–字符流中第一个不重复的字符


题目描述


请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

输出描述:

如果当前字符流没有存在出现一次的字符,返回#字符。


思路解析


这题本质上也是使用list进行循环添加,之后进行比较输出即可。


源代码


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Solution {
public  class Node {
      int val;
      char ch;
      Node(char ch) {
          this.ch =ch;
          this.val=1;
      }
  }
   String str="";
   public void Insert(char ch)
      {
          str=str+ch;
      }
   public char FirstAppearingOnce()
      {
     char flag='#';
     char[]ch=str.toCharArray();
     Set<Character>set=new HashSet<Character>();
     List<Node>list=new ArrayList<Node>();
     for(int i=0;i<ch.length;i++)
     {
       if(!set.contains(ch[i]))
       {
         set.add(ch[i]);
         Node node=new Node(ch[i]);
         list.add(node);
       }
       else
       {
         for(int j=0;j<list.size();j++)
         {
           if(list.get(j).ch==ch[i])
             list.get(j).val++;
         }
       }
     }
     for(int i=0;i<list.size();i++)
     {
       if(list.get(i).val==1)
       {
         flag=list.get(i).ch;
         break;
       }
     } 
     return flag;
      }
}


55题解–链表中环的入口结点


题目描述


给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。


思路解析


首先我们举一个出现环状的链表的例子。


20200811092910404.png


显然我们可以想到通过遍历的方式,但是一旦出现环,那么我们是遍历不完的,所以我们必须添加截止条件,每次我们遍历一个元素时就将他的值存入list之中,这样我们就能进行判断,如果list中不存在说明是第一次遍历到,否则就是第二次遍历到,第二次遍历到就说明已经出现环状,所以就可以直接返回该节点。如果没有环,那么遍历结束返回null即可。


源代码


/*
 public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}
*/
import java.util.ArrayList;
public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ArrayList<Integer>list=new ArrayList<Integer>();
    while(pHead!=null) 
    {
        //判断是否存在,第一次直接添加
      if(!list.contains(pHead.val))
        list.add(pHead.val);
      //第二次出现,说明出现环,直接返回该节点
      else {
        return pHead;
      }
      if(pHead.next!=null)
        pHead=pHead.next;
      else
        break;
    }
    //执行到这里说明链表已经遍历完毕所以不存在环,返回null即可
    return null;
    }
}



相关文章
剑指offer题目汇总(二)
剑指offer题目汇总(二)
|
存储 中间件
剑指offer(04-06)题解
剑指offer(04-06)题解
剑指offer(04-06)题解
剑指offer(25-30)题解
剑指offer(25-30)题解
剑指offer(25-30)题解
|
存储 算法
剑指offer(19-24)题解
剑指offer(19-24)题解
剑指offer(19-24)题解
|
机器人
剑指offer(61-67)题解
剑指offer(61-67)题解
剑指offer(61-67)题解