剑指 offer day10-day13

剑指 Offer 46. 把数字翻译成字符串

题目:

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,11 翻译成 “l”,25 翻译成 “z”。一个数字可能有多个翻译。
请实现一个函数,用来计算一个数字有多少种不同的翻译方法

题解(动态规划):

清晰图解

 public int translateNum(int num) {
        String s = String.valueOf(num);
        int a = 1, b = 1;
        for(int i = 2; i <= s.length(); i++) {
            String tmp = s.substring(i - 2, i);
            int c=tmp.compareTo("10") >= 0 && tmp.compareTo("25") <= 0 ? a + b : a;
            b = a;
            a = c;
        }
        return a;
    }

剑指 Offer 48. 最长不含重复字符的子字符串

题目:

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

题解(滑动窗口):

1.使用两个下标值slowfast来维护滑动窗口,fast不断前进来遍历字符串,并将字符及其下标存入map中;

2.对于每次循环,均需要判断当前fast指针所指字符在map中是否存在,若存在则将slow指针移动至该字符上次出现的位置,此时需要注意:该字符在map中存在并不代表此时窗口内存在重复字符,比如abba,因此 slow=Math.max(slow,map.get(array[fast])+1);

3.每次循环均需要更新max值。

public int lengthOfLongestSubstring(String s) {
        char[] array = s.toCharArray();
        int fast=0,slow=0,max=0;
        Map<Character,Integer> map = new HashMap<>();
        while (fast<s.length()){
            if (map.containsKey(array[fast])){
                slow=Math.max(slow,map.get(array[fast])+1);
            }
            map.put(array[fast],fast);
            fast++;
            max =  Math.max(max,fast-slow);
        }
        return max;
    }

剑指 Offer 18. 删除链表的节点

题目:

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。

题解:

复制头节点给temp节点,向后遍历,如果temp的下一个节点是所要找的,执行 temp.next=temp.next.next调整指针,直接break;返回头节点。

    public ListNode deleteNode(ListNode head, int val) {
        if (head.val==val){
            return head.next;
        }
        ListNode temp = head;
        while (temp!=null){
            if (temp.next.val==val){
                temp.next=temp.next.next;
                break;
            }
            temp = temp.next;
        }
        return head;
    }

剑指 Offer 22. 链表中倒数第k个节点

题目:

输入一个链表,输出该链表中倒数第k个节点。

例如:给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.

题解1(栈):

通过遍历链表将所有节点压栈,然后向外弹栈,返回第k个节点。

public ListNode getKthFromEnd(ListNode head, int k) {
        Stack<ListNode> stack = new Stack<>();
        while (head!=null){
            stack.add(head);
            head=head.next;
        }
        for (int i=0;i<k-1;i++){
            stack.pop();
        }
        ListNode res = stack.pop();
        return res;
    }

题解2(双指针):

1.定义两个节点指针slowfast,初始均指向头节点;

2.保持slow位置不变,向前移动fast,形成一个长度为k的窗口;

3.在fast指针未到达最后一个时,两个指针维持长度未k的窗口向前滑动;

4.当fast指针到达尾部时,此时slow指针所指位置即为倒数第k个,返回即可。

 public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode slow = head;
        ListNode fast = head;
        //创造一个区间为k的滑动窗口
        for (int i=0;i<k;i++){
            fast=fast.next;
        }
        //两个指针一起向后移动
        while (fast!=null){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }

剑指 Offer 25. 合并两个排序的链表

题目:

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

题解:

获取全部的节点值并存入list中,将排序之后的list转换为链表。

  public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //获取全部的节点值并存入list中
        List<Integer> list = new ArrayList<>();
        while (l1!=null){
            list.add(l1.val);
            l1=l1.next;
        }
        while (l2!=null){
            list.add(l2.val);
            l2=l2.next;
        }
        Collections.sort(list);
        //将排序之后的list转换为链表
        ListNode head = new ListNode(0);
        ListNode temp = head;
        for (int i=0;i<list.size();i++){
            ListNode node = new ListNode(list.get(i));
            temp.next=node;
            temp=temp.next;
        }
        return head.next;
    }

剑指 Offer 52. 两个链表的第一个公共节点

题目:

输入两个链表,找出它们的第一个公共节点。

题解:

1.A和B分别在其所在链表进行遍历,判断是否相等;

2.若节点A为空时,A和B还不相等,则另A从头开始遍历B链表;同理当B为空时,B继续从头开始遍历A链表3.当A和B相等时跳出循环有两种情况:一种是真的找到了公共节点,另一种是二者均走完了两个链表并且两个链表无公共节点,二者均为null;

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        ListNode headATemp = headA;
        ListNode headBTemp = headB;
        while (headA!=headB){
            if (headA==null){
                headA=headBTemp;
            }else {
                headA=headA.next;
            }
            if (headB==null){
                headB=headATemp;
            }else {
                headB=headB.next;
            }

        }
        return headA;
    }

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

题目:

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

题解1:

创建等长的数组res,遍历数组将奇数从前往后开始存储,偶数从后往前存储。

    public int[] exchange(int[] nums) {
        
        int[] res = new int[nums.length];
        int i=0;//从前往后移动  存储奇数
        int j= nums.length-1;  //从后往前移动 存储偶数
        for (int m=0;m<nums.length;m++){
            int a = nums[m];
            if (a%2==0){
                res[j]=a;
                j--;
            }else {
                res[i]=a;
                i++;
            }
        }
        return res;
    }

题解2(双指针):

1.定义两个下标ij,其中i从前往后寻找偶数,j从后往前寻找奇数;

2.如果i找到了偶数,则停止不再继续前进,等待j找到奇数然后二者互换;
同理,如果j找到了奇数,则停止不再继续前进,等待i找到偶数然后二者互换;
直至i>=j,循环结束。

    public int[] exchange(int[] nums) {

        int i=0;//从前往后移动
        int j= nums.length-1;  //从后往前移动
        while (i<j){
            if (nums[i]%2==0&&nums[j]%2!=0){
                int temp=nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
            }
            if (nums[i]%2!=0){
                i++;
            }
            if (nums[j]%2==0){
                j--;
            }
        }
        return nums;
    }

剑指 Offer 57. 和为s的两个数字

题目:

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

题解(双指针):

1.定义两个下标变量ij,分别初始化为0和length-1;

2.当i<j时,判断此时二者的和与target的关系:

如果大于的话,则 j - -;如果小于则 i + +;如果相等则break。

    public int[] twoSum(int[] nums, int target) {

        int[] res = new int[2];
        int i=0;
        int j=nums.length-1;
        while (i<j){
            if (nums[i]+nums[j]>target){
                j--;
            }
            if (nums[i]+nums[j]<target){
                i++;
            }
            if (nums[i]+nums[j]==target){
                res[0]=nums[i];
                res[1]=nums[j];
                break;
            }
        }
        return res;
    }

剑指 Offer 58 - I. 翻转单词顺序

题目:

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。

题解:

1.掉字符串开头和结尾的空格,按照单个或者多个空格进行划分;

2.遍历数组并入栈,弹栈并进行字符串拼接。

 public String reverseWords(String s) {

        Stack<String> stack = new Stack<>();
        String m = s.trim();//去掉字符串开头和结尾的空格
        String[] array = m.split("\\s+");//按照单个或者多个空格进行划分
        //遍历数组并入栈
        for (int i=0;i<array.length;i++){
            stack.add(array[i]);
        }
        String res ="";
        //弹栈并进行字符串拼接
        while (!stack.isEmpty()){
            res = res +" "+stack.pop();
        }
        return res.trim();
    }

最近的天气 让我觉得每次开门都像在开冰箱!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值