记录刷题第一题:牛客|字节跳动春招研发部分编程题汇总|3.雀魂启动

1.题目 

2.开始思路 

一开始以为弄个正常的排序数组然后判断即可,后来发现一个判断的大问题,即用数组的话我一开始用的核心判断逻辑是只是判断aaa型和abc型,但是示例2运行的时候发现不对劲了,因为还有abbccd型和aabbcc类型我还没有作判断.由此展开的还可以是嵌套了两个类型或以上的类型,比如abbbbccccddd型,aabbbcccd型等等.....用数组做这些逻辑的话会废非常大的功夫.所以可以另辟蹊径.

先贴上我一开始用数组作的思路

#include <iostream>
using namespace std;
// 快速排序函数
void quick_sort(int arr[], int left, int right) {
  if (left >= right) {
    return;
  }

  int pivot = arr[left]; // 选择第一个元素作为基准值
  int i = left, j = right;

  while (i < j) {
    while (i < j && arr[j] >= pivot) {
      j--;
    }
    arr[i] = arr[j];
    while (i < j && arr[i] <= pivot) {
      i++;
    }
    arr[j] = arr[i];
  }

  arr[i] = pivot; // 将基准值放到正确的位置

  quick_sort(arr, left, i - 1); // 递归对基准值左侧的子数组进行快速排序

  quick_sort(arr, i + 1, right); // 递归对基准值右侧的子数组进行快速排序
}


bool insert(int *pai, int *paiDemo, int new_pai) { // new_pai==1-9

  bool add = false;
  for (int i = 0; i < 14; i++) {//i have 13

    if (pai[i] == new_pai && i + 4 < 13)
      if ((pai[i] == pai[i + 1] && pai[i] == pai[i + 2] &&
           pai[i] == pai[i + 3]) &&pai[i]==
          pai[i + 4]) {
        return false;
      }

    if (pai[i] <= new_pai && i < 13) {
      paiDemo[i] = pai[i];
    } else {
      if (!add && i <= 13) {
        paiDemo[i] = new_pai;
        add = true;
      } else {
        paiDemo[i] = pai[i - 1];
      }
    }
  }
  return true;
}

int main() {
  int pai[14]={1, 1, 1, 1, 2, 2, 3, 3, 5, 6, 7, 8, 9};
  // for (int i = 0; i < 14; i++) {
  //   cin >> pai[i];
  // }
  
  quick_sort(pai, 0, 12);
  for(int ak=0;ak<14;ak++){
        cout<<pai[ak];
      }
      cout<<endl<<"牌已经有序"<<endl;

  //已经排完序的pai
  int count=0;
  // int j=9;
  for (int j = 1; j < 10; j++) { // j为听牌数字 1-9
    int paiDemo[14];
    
    if (insert(pai, paiDemo, j)) {
      //逻辑coding...

      
      for(int i=0; i<13; i++){//  i是将牌下标
        
        if(paiDemo[i]==paiDemo[i+1]&&i+1<=13){
          int k=0;//k 是牌下标0-13
          bool ak=true;
          for( ; k<14; k++){

            int index[6];
            if(k==i){
              k+=1;
              continue;
            }else if(k+1==i){
              if(k+4>=13){
                ak=false;
                break;
                
              }
              index[0]=k;
              index[1]=k+3;
              index[2]=k+4;
            }else if(k+2==i){
              if(k+4>=13){
                ak=false;
                break;
              }
              index[0]=k;
              index[1]=k+1;
              index[2]=k+4;
            }else{
              if(k+2>=13){
                ak=false;
                break;
              }
              index[0]=k;
              index[1]=k+1;
              index[2]=k+2;
            }

            if(paiDemo[index[0]]==paiDemo[index[1]]&&paiDemo[index[0]]==paiDemo[index[2]]){//如 111型
              k=index[2];
            }else if(paiDemo[index[0]]==paiDemo[index[1]]-1&&paiDemo[index[1]]==paiDemo[index[2]]-1){//如123型
              k=index[2]; 
            }else{
              ak=false;
              break;
            }
          }
          if(ak){
            count++;
            break;
          }

        }
        
      }
      
      
    } 
  }

cout<<"this is count "<<count<<endl;
  while(1){}
}
// 64 位输出请用 printf("%lld")

3.想到的正确思路

        可以自己创建一个关于牌的class,包含增删改查,但是会有点麻烦,于是我把牌的1-9绑定a-i的string类型.就能调用string类型的增删改查了;

        核心判断:  首先循环将牌(即雀头),把两个符合的将牌用string类型的erase删去,再循环判断是否有aaa型,有的话就删去循环继续,没有的话去找是否有abc型,有的话就删去循环继续,没有的话都不用找了,直接就不成立.以上两个循环可以确立一种听牌的情况,只要循环每一个听牌情况即可求出本题答案.

#include <iostream>
using namespace std;

class my_arr {
public:
  string arr;
  my_arr() { arr = ""; }
  int change_string_num(string str) {

    if (str == "a")
      return 1;
    else if (str == "b")
      return 2;
    else if (str == "c")
      return 3;
    else if (str == "d")
      return 4;
    else if (str == "e")
      return 5;
    else if (str == "f")
      return 6;
    else if (str == "g")
      return 7;
    else if (str == "h")
      return 8;
    else if (str == "i")
      return 9;
    else
      return -1;
  }
  string change_num_string(int num) {
    switch (num) {
    case 1:
      return "a";
    case 2:
      return "b";
    case 3:
      return "c";
    case 4:
      return "d";
    case 5:
      return "e";
    case 6:
      return "f";
    case 7:
      return "g";
    case 8:
      return "h";
    case 9:
      return "i";
    default:
      return "-1";
    }
  }

  void add(int mum) { arr += change_num_string(mum); }
};

// 快速排序函数
void quick_sort(int arr[], int left, int right) {
  if (left >= right) {
    return;
  }

  int pivot = arr[left]; // 选择第一个元素作为基准值
  int i = left, j = right;

  while (i < j) {
    while (i < j && arr[j] >= pivot) {
      j--;
    }
    arr[i] = arr[j];
    while (i < j && arr[i] <= pivot) {
      i++;
    }
    arr[j] = arr[i];
  }

  arr[i] = pivot; // 将基准值放到正确的位置

  quick_sort(arr, left, i - 1); // 递归对基准值左侧的子数组进行快速排序

  quick_sort(arr, i + 1, right); // 递归对基准值右侧的子数组进行快速排序
}

bool insert(int *pai, int *paiDemo, int new_pai) { // new_pai==1-9

  bool add = false;
  for (int i = 0; i < 14; i++) { // i have 13

    if (pai[i] == new_pai && i + 4 < 13)
      if (pai[i] == pai[i + 1] && pai[i] == pai[i + 2] && pai[i] == pai[i + 3]) {
        return false;
      }

    if (pai[i] <= new_pai && i < 13) {
      paiDemo[i] = pai[i];
    } else {
      if (!add && i <= 13) {
        paiDemo[i] = new_pai;
        add = true;
      } else {
        paiDemo[i] = pai[i - 1];
      }
    }
  }
  return true;
}

int main() {
  // int pai[14] = {1 ,1 ,1 ,1 ,2 ,2 ,3 ,3 ,5 ,6, 7 ,8 ,9};
  int pai[14];
  for (int i = 0; i < 14; i++) {
    cin >> pai[i];
  }

  quick_sort(pai, 0, 12);
  for (int ak = 0; ak < 14; ak++) {
    cout << pai[ak];
  }
  cout << endl << "牌已经有序" << endl;

  //已经排完序的pai
  int count = 0;
  int count_tin[9];
  my_arr *paiArr;
  // int j=9;
  for (int j = 1; j < 10; j++) { // j为听牌数字 1-9
    int paiDemo[14];

    if (insert(pai, paiDemo, j)) {

      
      //逻辑coding...
      for (int i = 0; i < 13; i++) { //  i是将牌下标

        paiArr = new my_arr(); //逻辑是对paiArr操作
        for (int k = 0; k < 14; k++) {
          paiArr->add(paiDemo[k]);
        }

        if (paiDemo[i] == paiDemo[i + 1] && i + 1 <= 13) {
            //把将牌删了
          paiArr->arr.erase(i,2);
           
          bool ak = true;
          while (1) {

            if (paiArr->arr.length() >= 3) {
              if (paiArr->arr[0] == paiArr->arr[1] &&
                  paiArr->arr[0] == paiArr->arr[2]) { //组合刻子
                paiArr->arr.erase(0,3);
                
              } else { //组合顺子
                string now_str,next2_str;//下一个字母
                now_str.push_back( paiArr->arr[0]);  
                int next = paiArr->change_string_num(now_str)+1; //下一个pai数字
                int next_index = paiArr->arr.find(paiArr->change_num_string(next)); //下一个数字下标
                if (next_index > 0 && next_index < 14) {
                  int next2_index =
                      paiArr->arr.find(paiArr->change_num_string(next + 1));
                  if (next2_index > next_index && next2_index < 14) {
                    //有顺子
                    paiArr->arr.erase(0,1);
                    paiArr->arr.erase(next_index-1,1);
                    paiArr->arr.erase(next2_index-2,1);
                    continue;
                  }
                }
                //没有顺子
                ak = false;
                break;
              }
            } else {
              if (paiArr->arr.length() != 0) {
                ak = false;
                break;
              }else{
                break;
              }
            }
          }

          if (ak) {
            
            count_tin[count]=j;
            count++;
            break;
          }
        }


        //跳过相同的将牌
        while(paiDemo[i+1]==paiDemo[i]){         
          i++;
        }
        
      }
      
    }
  }
  for(int aj=0;aj<count;aj++){
    cout<<count_tin[aj]<<" ";
  }
  cout<<endl;



  cout << "this is count " << count << endl;
  while (1) {
    getchar();
  }
}

         4.总结

耗费时间是一天,主要是需要掌握对string类型的用法和逻辑判断不是用数组而是用string类型.

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值