java字符串切割_微软常见面试题之数组和字符串类

26ec02b4f59e640974afbacd6c6f1ba7.png
此篇文章来自我的公众号,实思。查看更多内容,请关注公众号。文章底部有二维码。

作为码农,很多人都需要刷题。我在leetcode上面,发现了微软专辑系列。leetcode列出了微软比较常见的面试题,分了八块内容。分别是数组和字符串,链表,树和图,回溯,排序和搜索,动态规划,设计和其他。

今天,说点简单的。说说在数组和字符串里面,微软常见的面试题。leetcode列出了十几道。我抽三道比较简单的leetcode的题目来讲解。

第一道,Reverse String

Write a function that reverses a string. The input string is given as an array of characters char[].

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

You may assume all the characters consist of printable ascii characters.

Input: ["h","e","l","l","o"]
Output: ["o","l","l","e","h"]
Input: ["H","a","n","n","a","h"]
Output: ["h","a","n","n","a","H"]

其实这道题,如果熟悉python的人,一行就解决了。Reverse String也是微软问的比较多的一道题。

class Solution:
    def reverseString(self, s):
        s.reverse()

就是简单的把字母逆排序一下。python的reverse()就可以解决了。我记得C++里面也有reverse,有兴趣的可以试试看。

reverse(str.begin(),str.end());

当然,也可以用java和C++。用递归也可以解决。设置,左右两个指针,然后交换指针即可。但是要注意,更换以后,原字符串的大小也要发生变化,左边需要加以,右边需要减一。来适应更改后的长度。

首先写出递归方程。

Base Condition: left > right, 即不存在。

If left <= right, 交换左右,并且更改长度。

看代码:

class Solution {
  public void helper(char[] s, int left, int right) {
    if (left >= right) return;
    char tmp = s[left];
    s[left++] = s[right];
    s[right--] = tmp;
    helper(s, left, right);
  }

  public void reverseString(char[] s) {
    helper(s, 0, s.length - 1);
  }
}

其实用完递归以后,我将觉得差不多好像就可以了。但是leetcode给了一个更炫酷的解法。请看下图:

88d6b23d7edeb7379cbbbfca218be94e.png

这个方法,更快,而且更加的容易理解整个过程!每次只需要对首尾两个进行交换,然后交换即可。每次左边再自增加一,右边减一。慢慢的检索到中间!So Smart!

class Solution {
    public void reverseString(char[] s) {
        int left = 0, right = s.length - 1;
        while (left < right) {
            char tmp = s[left];
            s[left++] = s[right];
            s[right--] = tmp;
        }
    }
}

第二道:Reverse Words in a String.

Given an input string, reverse the string word by word.

Example:

Input: "the sky is blue"
output: "blue is sky the"
Input: "a good example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.
Input: " hello world! "
Output: "world! hello"
Explanation: Your reversed string should not contain leading or trailing spaces.

这道题,我一开始没有意识到复杂程度。我记得阿里巴巴也喜欢问这种类似的逆序句子。我一开始提交的代码是:

class Solution {
   public String reverseWords(String s) {
      stringstream ss(s);
      string res="",tmp;  
      while(s>tmp){
         if(res =="") 
             res = tmp;
         else
             res = tmp + " " + res;
       }
      cout<<res<<endl;
    }
}

该解法,很有效也很简单。我用stringstream进行分割语句,然后把它存在一个res里面,然后每次倒序相加。最后输出该语句,完成逆序。

第二种思路就是把整个句子进行看作整体,进行反转。然后反转每个单词,反转完以后,把多余的空格删除。注意,在反转完整体以后,还要把前后的空格也删掉。

class Solution {
  public:
  string reverseWords(string s) {
     // reverse the whole string
    reverse(s.begin(), s.end());

    int n = s.size();
    int idx = 0;
    for (int start = 0; start < n; ++start) {
    if (s[start] != ' ') {
     // go to the beginning of the word
     if (idx != 0) s[idx++] = ' ';

     // go to the end of the word
    int end = start;
    while (end < n && s[end] != ' ') s[idx++] = s[end++];

      // reverse the word
        reverse(s.begin() + idx - (end - start), s.begin() + idx);

      // move to the next word
        start = end;
      }
    }
     s.erase(s.begin() + idx, s.end());
     return s;
  }
}

第三种,我觉得可以用到C++和Java里面的reverse。当我把单个单词切割出来以后,我把它存在一个数组里面,然后逆序输出这样数组就好了。但要注意删除首尾的额外空间。

class Solution {
  public String reverseWords(String s) {
    // remove leading spaces
    s = s.trim();
    // split by multiple spaces
    List<String> wordList = Arrays.asList(s.split("s+"));
    Collections.reverse(wordList);
    return String.join(" ", wordList);
  }
}

第三道:Sprial Matrix

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

Example:

Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Input:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]

这一道其实就是矩阵变换的题目。Java里面的有矩阵可以用。想要把数字按照逆时针输出,我觉得只要把握好相应的行列,即可。

因为是逆时针的一个圈,所以我们可以把这些数字放在一个新的数组里面,然后存放在里面即可。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List ans = new ArrayList();
        if (matrix.length == 0) return ans;
        int R = matrix.length, C = matrix[0].length;
        boolean[][] seen = new boolean[R][C];
        int[] dr = {0, 1, 0, -1};
        int[] dc = {1, 0, -1, 0};
        int r = 0, c = 0, di = 0;
        for (int i = 0; i < R * C; i++) {
            ans.add(matrix[r][c]);
            seen[r][c] = true;
            int cr = r + dr[di];
            int cc = c + dc[di];
            if (0 <= cr && cr < R && 0 <= cc && cc < C && !seen[cr][cc]){
                r = cr;
                c = cc;
            } else {
                di = (di + 1) % 4;
                r += dr[di];
                c += dc[di];
            }
        }
        return ans;
    }
}

leetcode上面给了一个更加炫酷的方法。

78b69cb9d89c31bcdf298c62d2b4273a.png

按照这样的方法,然后依次输出每行的结果,按照上,右,下,左进行按次序输出每行的数字。重新组成一个矩阵。

简直太智慧了!

class Solution {
    public List < Integer > spiralOrder(int[][] matrix) {
        List ans = new ArrayList();
        if (matrix.length == 0)
            return ans;
        int r1 = 0, r2 = matrix.length - 1;
        int c1 = 0, c2 = matrix[0].length - 1;
        while (r1 <= r2 && c1 <= c2) {
            for (int c = c1; c <= c2; c++) ans.add(matrix[r1][c]);
            for (int r = r1 + 1; r <= r2; r++) ans.add(matrix[r][c2]);
            if (r1 < r2 && c1 < c2) {
                for (int c = c2 - 1; c > c1; c--) ans.add(matrix[r2][c]);
                for (int r = r2; r > r1; r--) ans.add(matrix[r][c1]);
            }
            r1++;
            r2--;
            c1++;
            c2--;
        }
        return ans;
    }
}

以上,就是这三道例题。如有问题,请随时告知我。我将立刻更改。能力赢弱,欢迎指正。

Andrew Ni

可以关注我的公众号联系我。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值