当前位置: 代码迷 >> 综合 >> 剑指 offer day10-day13
  详细解决方案

剑指 offer day10-day13

热度:59   发布时间:2023-11-24 17:18:19.0

剑指 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();}

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

  相关解决方案