leetcode_336 Palindrome Pairs

  • 题目分析:

    给定一组唯一的单词,从中寻找所有的下标对(i,j),使得对应下标的单词拼接,即words[i] + words[j]是回文。

  • 解题思路:

    利用字典map保存单词与下标的键值对;

    1)若当前的单词word本身是回文,且words中存在空串,则将空串下标bidx与idx加入答案;

    2)若房钱单词的逆序串在words中,则将逆序串下标rids与idx加入答案;

    3)将当前单词word拆分为左右两半left,right

    3.1)若left为回文,并且right的逆序在words中,则将right的逆序串下标rridx与idx加入答案;
    
    3.2)若right为回文,并且left的逆序串在words中,则将left的逆序串下标idx与rlidx加入答案。
    
  • 实现程序

    • C++版本

      // 方法1,借助set实现
      class Solution 
      {
          public:
              bool isValid(string temp, int left, int right)
              {
                  while (left < right)
                  {
                      if (temp[left++] != temp[right--])
                          return false;
                  }
                  return true;
              }
              vector< vector<int> > palindromePairs(vector<string> & words)
              {
                  vector< vector<int> > result;
                  map<string, int> mp;
                  set<int> s;
                  // 遍历字符串数组,将所有的字符串保存在map中,同时记录其对应的位置,同时利用set保存其字符串的长度 
                  for (int i = 0; i < words.size(); i++)
                  {
                      mp[words[i]] = i;
                      s.insert(words[i].size());
                  }
                  // 遍历字符创数组,将字符串进行逆转,查找其是否存在回文字符串 
                  for (int i = 0; i < words.size(); i++)
                  {
                      string temp = words[i];
                      int len = temp.size();
                      reverse(temp.begin(), temp.end());
                      // 查找是否存在转置后的字符串,且其对应的位置不为temp的位置i,存在,则找到一对回文 
                      if (mp.count(temp) && mp[temp] != i)
                      {
                          vector<int> tp;
                          tp.push_back(i);
                          tp.push_back(mp[temp]);
                          result.push_back(tp);
                      }
                      set<int>::iterator it;
                      // 分析其部分字符串中是否存在构成回文的字符串 
                      for (it = s.begin(); it != s.find(len); it++)
                      {
                          int d = *it;
                          if (isValid(temp, 0, len - d - 1) && mp.count(temp.substr(len - d)))
                          {
                              vector<int> tp;
                              tp.push_back(i);
                              tp.push_back(mp[temp.substr(len - d)]);
                              result.push_back(tp);
                          }
                          if (isValid(temp, d, len - 1) && mp.count(temp.substr(0, d)))
                          {
                              vector<int> tp;
                              tp.push_back(mp[temp.substr(0, d)]);
                              tp.push_back(i);
                              result.push_back(tp);
                          }
                      } 
                  } 
                  return result;
              }
      };
      
      // 方法2 不借助set实现
      class Solution 
      {
          public:
              // 判断字符串是否是回文 
              bool isValid(string temp)
              {
                  for (int i = 0; i < temp.size() / 2; i++)
                  {
                      if (temp[i] != temp[temp.size() - 1 - i])
                          return false;
                  }
                  return true;
              } 
              vector< vector<int> > palindromePairs(vector<string> &words)
              {
                  vector< vector<int> > result;
                  map<string, int> mp;
                  // 利用map存储每个单词,及其在字符串中的位置 
                  for (int i = 0; i < words.size(); i++)
                  {
                      mp[words[i]] = i;
                  }
                  // 遍历所有单词 
                  for (int i = 0; i < words.size(); i++)
                  {
                      int l = 0;   // 记录左边移动字符数 
                      int r = 0;   // 记录右边移动字符数 
                      while (l <= r)
                      {
                          string tp = words[i].substr(l, r - l);
                          // 逆转子串 
                          reverse(tp.begin(), tp.end());
                          // 判断是否存在逆串,且剩余字符串部分构成回文,先判断右边,在判断左边 
                          if (mp.count(tp) && i != mp[tp] && isValid(words[i].substr(l == 0 ? r : 0, l == 0 ? words[i].size() - r : l)))
                          {
                              // 对应整个字符串构成回文情况 
                              if (l == 0)
                              {
                                  vector<int> t;
                                  t.push_back(i);
                                  t.push_back(mp[tp]);
                                  result.push_back(t);
                              }
                              // 对应字符串的子串构成回文 
                              else
                              {
                                  vector<int> t;
                                  t.push_back(mp[tp]);
                                  t.push_back(i);
                                  result.push_back(t);
                              }
                          } 
                          // 移动左或右标志 
                          if (r < words.size())
                              r++;
                          else
                              l++;
                      }
                  }
                  return result;
              }
      };
      
    • Java版本

      boolean isValid(String temp){
          for (int i = 0; i < temp.length() / 2; i++){
              if (temp.charAt(i) != temp.charAt(temp.length() - 1 - i))
                  return false;
          }
          return true;
      }
      public List<List<Integer>> palindromePairs1(String[] words) {
          List<List<Integer>> result = new ArrayList<>();
          Map<String, Integer> map = new HashMap<>();
          for (int i = 0; i < words.length; i++){
              map.put(words[i], i);
          }
          for (int i = 0; i < words.length; i++){
              int l = 0;
              int r = 0;
              while (l <= r){
                  String substr = words[i].substring(l, r);
                  Integer j = map.get(new StringBuilder(substr).reverse().toString());
                  // 处理右边
                  if (j != null && i != j && l == 0 && isValid(words[i].substring(r, words[i].length()))){
                      ArrayList<Integer> t = new ArrayList<Integer>();
                      t.add(i);
                      t.add(j);
                      result.add(t);
                  } else {
                      // 处理左边
                      if (j != null && i != j && l != 0 && isValid(words[i].substring(0, l))){
                          ArrayList<Integer> t = new ArrayList<Integer>();
                          t.add(j);
                          t.add(i);
                          result.add(t);
                      }
                  }
                  // 移动左右标志
                  if (r == words[i].length())
                      l++;
                  else 
                      r++;
              }
          }
          return result;
      }
      
  • 参考文献

    http://bookshadow.com/weblog/2016/03/10/leetcode-palindrome-pairs/

    http://www.cnblogs.com/grandyang/p/5272039.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值