LeetCode中等题(一)

题目一:

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

 

分析:这道题目是一个链表题,对链表元素相加得出一个新的链表,那么怎么能实现链表元素的相加呢?其实这和我们实现两个数相加很类似,首先应该从个位数开始,如果之和大于10则将向前进一位。

1、创建一个新的链表,用于返回最后相加和的结果,ListNode DummyNode=new ListNode(0);

2、设置一些指向链表的节点,分别指向l1,l2,DummyNode, p1=l1,p2=l2,curr=DummyNode;

3、开始遍历列表,进行求和,首先获取了l1,l2头节点的值,在进行相加  int x=(p1!=null)? p1.val:0;    int y=(p2!=null)? p2.val:0;   int sum=x+y+count;

4、这里的难点在于求和后的结果超过10应该怎么办?我们应该将其记录下来,然后添加到下一次求和中,如上式的sum,记录的方式为:sum=sum/10,结果是0或者1;

5、curr节点应该添加一个新的节点,并且存放所求得的和值,方式为curr.next=new ListCode(sum%10);

6、将curr,p1,p2分别向后移动指针, curr=curr.next;    if(p1!=null) p1=p1.next;    if(p2!=null) p2=p2.next;

7、如果在最后一轮循环中count大于1,这需要新创建一个节点  curr.next=new ListNode(count);

8、返回链表DummyNode.next,因为第一个节点为0,无意义。

 

具体实现过程:

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        
        ListNode DummyNode=new ListNode(0);
        ListNode p1=l1,p2=l2,curr=DummyNode;
        
        int count=0;    
        while(p1!=null||p2!=null)
        {
            int x=(p1!=null)? p1.val:0;
            int y=(p2!=null)? p2.val:0;
            int sum=x+y+count;
            count=sum/10;
            
            curr.next=new ListNode(sum%10);
            curr=curr.next;
            if(p1!=null) p1=p1.next;
            if(p2!=null) p2=p2.next;
        }
        
        if(count>0)
            curr.next=new ListNode(count);
        
        return DummyNode.next;
    }
}

 

 

题目二:

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

 

方法一:暴力法

1、获得字符串长度,用二次循环直接遍历所有的可能性 for(int i=0; i<s.lenght;i++) for(int j=i+1;j<s.lenght;j++)

2、获取所有字符串长度的最大值,ans=Math.max(ans,j-i)

3、这里最主要的一部是获取字符串长度的比较,首先设置一个集合Set<Character> set=new HashSet<>();

4、将字符串s,i,j的位置传入判断函数,获取传入的值Character ch=s.CharAt(i),获取索引i的值;

5、判断ch值是否重复,if(set.contain(ch)) return false,set.add(ch);

6、返回true;

具体代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        int n=s.length();
        int ans=0;
        
        for(int i=0;i<n;i++)
            for(int j=i+1;j<=n;j++)
            {
                if(JugleFun(s,i,j)) ans=Math.max(ans, j-i);
            }
        
        return ans;
    }
    
    public boolean JugleFun(String s,int start,int end)
    {
        Set<Character> set=new HashSet<>();
        
        for(int i=start;i<end;i++)
        {
            Character ch=s.charAt(i);
            if(set.contains(ch)) return false;
            set.add(ch);
        }
        
        return true;
    }
}

 

方法二:滑动窗口

1、使用i=0,j=0两个值向后逐个滑动;

2、主要的思想:如果遍历过字符串为不重复子串,就没必要再去重复判断,如果1234561,i=1,j=1,直接从i=2和j=1进行判断;

3、if(!set.contain(s.charAt(j))),set.add(s.char(j++))  否则set.remove(s.charAt(i++));

具体代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        int n=s.length();
        int i=0,j=0,ans=0;
        Set<Character> set=new HashSet<>();
        
        while(i<n&&j<n)
        {
            if(!set.contains(s.charAt(j)))
            {
                set.add(s.charAt(j++));
                ans=Math.max(ans, j-i);
            }
            else {
                set.remove(s.charAt(i++));
            }
        }
        
        return ans;
    }
}

 

题目三:

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

示例 1:

输入: "()"
输出: true

 

分析:

1、字符的两两匹配问题,先将其放入哈希表中,HashMap<Character,Character> hashmap=new HashMap<>();

2、在构造函数中进行初始化,hashmap.put(')','(');

3、应该使用栈数据结构,将放入的元素和栈顶元素对比,Stack<Character> stack=new Stack<>(),获取串元素:k=s.CharAt(i);

4、如果是哈希表中的键,将进行对比,否则直接压栈,if(hashmap.containKey(c)), 获取栈顶元素:Character topElem=stack.empty()? '#':stack.pop();

5、比较栈顶元素和要入栈的元素是否相同,if(topElem!=hashmap.get(c))

6、返回栈是否为空,return stack.empty();

 

具体代码:

class Solution {
    
    private HashMap<Character, Character> hashMap=new HashMap<Character,Character>();
    
    public Solution()
    {
        hashMap.put(')', '(');
        hashMap.put('}', '{');
        hashMap.put(']', '[');
    }
    
    public boolean isValid(String s) {
        
        Stack<Character> stack=new Stack<>();
        
        for(int i=0;i<s.length();i++)
        {
            char c=s.charAt(i);
            
            if(hashMap.containsKey(c))
            {
                Character topEle=stack.empty()? '#':stack.pop();
                
                if(topEle!=hashMap.get(c))
                    return false;
            }
            
            else {
                stack.push(c);
            }
        }        
        return stack.empty();
    }
}

 

题目四:

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

 

方法一:

1、删除倒数第n个节点,先应该遍历出链表的长度,然后用lenght=length-n;

2、判断链表长度定位到删除的位置,if(lenght>0) curr=curr.next;

3、需要设置两个节点,一个用来遍历curr,另一个指向头结点,ListNode dummy=new ListNode;

4、返回dummy.next;

 

具体代码:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        
        ListNode curr=head;
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        int count=0;
        
        while(curr!=null)
        {
            count++;
            curr=curr.next;            
        }
count
-=n; curr=dummy; while(count>0) { count--; curr=curr.next; } curr.next=curr.next.next; return dummy.next; } }

 

方法二:

分析:

1、采用双指针实现,first指针先执行n步,然后second指针开始执行;

2、直到first为空,停止执行second;

3、将second指针指向下一个节点second.next=second.next.next;

4、开始设置哑结点指向头结点,first和second都指向dummy;

 

具体代码:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode first=dummy;
        ListNode second=dummy;
        
        for(int i=1;i<=n+1;i++)
        {
            first=first.next;
        }
        
        while(first!=null)
        {
            first=first.next;
            second=second.next;
        }
        
        second.next=second.next.next;
        
        return dummy.next;
    }
}

 

题目五:

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

 

方法一:暴力法

判断字符串中的回文,并将最大的回文串返回

1、将所有的字符串进行遍历,判断每个字符串是否为回文;

2、可以另外设置一个函数进行判断,判断字符串的第一位和最后一位是否相同即可,即if(s.charAt(i)==s.charAt(lenght-i-1))

3、设置返回的字符串为ans=" ";如果字符串为回文,那么返回最大的字符串,ma=0;if(str.lengt>0),ans=str,ma=Math.max(max,str.lenght);

4、返回length;

class Solution {
    public String longestPalindrome(String s) {
        
        String ans="";
        int ma=0;
        
        for(int i=0;i<s.length();i++)
            for(int j=i+1;j<=s.length();j++)
            {     
                String str=s.substring(i,j);
                if(isHuiWei(str)&&str.length()>ma)
                {
                    ans=s.substring(i,j);
                    ma=Math.max(ma, ans.length());
                }
            }
        return ans;
    }
    
    public boolean isHuiWei(String s)
    {
        
        int len=s.length();
        for(int i=0;i<len/2;i++)
        {
            if(s.charAt(i)!=s.charAt(len-i-1))
            {
                return false;
            }
        }       
        return true;
    }
    
}

 

方法二:动态规划

class Solution {
    public String longestPalindrome(String s) {
        
        int len=s.length();
        if(len<=1)
            return s;
        
        int longpa=1;
        String string=s.substring(0,1);
        boolean[][] dp=new boolean[len][len];
        
        for(int r=1;r<len;r++)
            for(int l=0;l<r;l++)
            {
                if(s.charAt(l)==s.charAt(r)&&(r-l<=2||dp[l+1][r-1]))
                {
                    dp[l][r]=true;
                    if(r-l+1>longpa)
                    {
                        longpa=r-l+1;
                        string=s.substring(l,r+1);
                    }
                }            
            }
        return string;
    }
}

 

转载于:https://www.cnblogs.com/Optimism/p/11272814.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值