有的用php代码实现
1.斐波那契数列 – 面试题9
function fibonaci_1($n){
if($n < 2){
return $n == 0 ? 0 : 1;
}
return fibonaci_1($n - 1) + fibonaci_1($n - 2);
}
var_dump(fibonaci_1(10)); ///int(55)
var_dump(fibonaci_1(30)); //int(832040)
//斐波那契数列-- 从前来后计算 -- 时间复杂度是O(n)---比递归的效率高
function fibonaci_2($n){
if($n <= 0){
return 0;
}else if($n == 1){
return 1;
}
$num1 = 0;
$num2 = 1;
$res = 0;
for($i = 2; $i <= $n; $i++){
$res = $num1 + $num2;
$num1 = $num2;
$num2 = $res;
}
return $res;
}
var_dump(fibonaci_2(30)); //int(832040)
2.计算二进制中的1的个数 – 面试题10
//计算二进制中的1的个数 1. 判断最后一位是不是1, 如果是 则 统计 如果不是 循环右移一位 ------- 不能有负数,, 否则死循环
function munber_of_1_1($num){
$count = 0;
while($num){
if($num & 1){
$count ++;
}
$num = $num >> 1;
}
return $count;
}
var_dump(munber_of_1_1(9));
//2. 将源数据减去一之后 和 源数据与运算 可以将最右边出现的1变成0 比如1100 和 1011 与运算之后就是1000 -- 这个算法比较屌
function number_of_1_2($num){
$count = 0;
while($num){
$count ++;
$num = $num & ($num - 1);
}
return $count;
}
var_dump(number_of_1_2(9));
3.数值的整数次方, 不用内置函数–面试题11
<?php
//实现一个double类型的整数次方, 不能用系统函数 power(double base, int exponent)
//1.利用次方的原理, 有多少个exponent,base就乘几次
function power_1($base, $exponent){
$res = 1.0;
for($i = 0; $i < $exponent; $i++){
$res *= $base;
}
return $res;
}
var_dump(power_1(2.2, 2)); //double(4.84)
var_dump(power_1(0.0, 2)); //double(1)
var_dump(power_1(0.0, 0)); //double(0) ---不正确
var_dump(power_1(23.2, -2)); //double(1) -- 不能处理指数是负数
//2. 加错误处理 如果指数是负数, 先计算正数的,最后在取倒数 但0 没有倒数
function power_2($base, $exponent){
if($exponent == 0){
return 0;
}else if($exponent == 1){
return 1;
}
if(equal($base, 0.0) && $exponent < 0){ //0 没有倒数
return 0.0;
}
$abs_exponent = $exponent;
if($exponent < 0){ //指数为负数
$abs_exponent = -$exponent;
}
$res = 1.0;
for($i = 0; $i < $abs_exponent; $i++){
$res *= $base;
}
if($exponent < 0){ //判断指数是否是负数
return 1.0 / $res;
}else{
return $res;
}
}
function equal($num1, $num2){ //比较float型, -- 检查是不是 为0
if(($num1 - $num2 < 0.000001) && ($num1 - $num2 > -0.000001)){
return true;
}else{
return false;
}
}
var_dump(power_2(2.2, 2)); //double(4.84)
var_dump(power_2(0.0, 2)); //double(0)
var_dump(power_2(0.0, 0)); //int(0)
var_dump(power_2(-2.2, 3)); //double(-10.648)
var_dump(power_2(2.2, -3)); //double(0.093914350112697)
var_dump(power_2(-2.2, -3)); //double(-0.093914350112697)
var_dump(power_2(0.0, -2)); //double(0)
//3.更加高效的方式 比如3^9 = (((3*3)^2)^2)*3 -- 利用递归实现
// a^n -- 指数n为偶数 则 计算公式: a^(n/2) * a^(n/2)
//-- 指数n为奇数 则 计算公式: a^(n/2) * a^(n/2) * a
function power_3($base, $exponent){
if($exponent == 0){
return 1;
}else if($exponent == 1){
return $base;
}
if(equal($base, 0.0) && $exponent < 0){ //0 没有倒数
return 0.0;
}
$abs_exponent = $exponent;
if($exponent < 0){ //指数为负数
$abs_exponent = -$exponent;
}
$res = power_3($base, $abs_exponent >> 1); // >> 1 相当于/2 效率更高
$res *= $res;
if($abs_exponent & 0x1 == 1){ //判断是否是奇数
$res *= $base;
if($exponent < 0){ //指数为负数, 最后去倒数
$res = 1.0 / $res;
}
}else{
if($exponent < 0){
$res = 1.0 / $res;
}
}
return $res;
}
var_dump(power_3(2.2, 2)); //double(4.84)
var_dump(power_3(0.0, 2)); //double(0)
var_dump(power_3(0.0, 0)); //int(0)
var_dump(power_3(-2.2, 3)); //double(-10.648)
var_dump(power_3(2.2, -3)); //double(0.093914350112697)
var_dump(power_3(-2.2, -3)); //double(-0.093914350112697)
var_dump(power_3(0.0, -2)); //double(0)
var_dump(power_3(4, 34)); //double(2.9514790517935E+20)
?>
4.输入数字n打印 1 到 最大n位十进制数 比如 位数是3 打印1…999 – 面试题12
//输入数字n打印 1 到 最大n位十进制数 比如 位数是3 打印1...999
//1. 考察的知识点: 大数溢出问题, 就是如果用 for循环则 存在大数溢出问题
function print_1_to_max_n_number_1($n){
if($n <= 0){
return;
}
$number = 1;
while($n--){
$number *= 10;
}
for($i = 0; $i < $number ;$i++){
echo $i ,' ';
}
}
print_1_to_max_n_number_1(3);
//2. 使用数字排列的解法,每一位上都是从0到9进行排列 便是题目的要求 --递归实现
5.在O(1)时间删除链表结点 – 面试题13
//在O(1)时间删除链表结点
//题目: 给定单链表的头指针和一个结点指针, 定义一个函数在O(1)时间删除该结点
//链表的结点定义:
class ListNode{
public $m_nValue = '';
public $m_pNext = null;
}
// 由于题目给定了要删除的结点, 所以不用在头部尽心查找了, 但是给定的值要删除的结点所以只能删除结点后的元素(前一个结点没有定位到)
// 删除思想 将删除结点的值设置为删除结点下一个结点的值, 删除结点下一个结点指向下一个结点的结点, 然后删除下一个结点
// 删除有三种情况 1. 链表只有一个结点; 2. 链表有多个结点删除的是未节点; 3. 链表有多个结点删除的是中间结点
function delete_node($node_head, $node_delete){
if(!$node_head || !$node_delete){
echo '结点有问题';
return;
}
//第三种情况
if($node_delete->m_pNext != null){
$node_delete->m_nValue = $node_delete->m_pNext->m_nValue;
$node_delete->m_pNext = $node_delete->m_pNext->m_pNext;
unset($node_delete->m_pNext);
}
//第一种情况 --
else if($node_delete == $node_head){
unset($node_delete);
$node_head = null;
}
//第二种情况
else if($node_delete->m_pNext == null){
$pNode = $node_head;
//找到$node_delete的前一个结点
while($pNode->m_pNext != $node_delete){
$pNode = $pNode->m_pNext;
}
unset($node_delete);
$pNode->m_pNext = null;
}
}
6.调整数组顺序使奇数位于偶数前面 – 面试题14
//调整数组顺序使奇数位于偶数前面
#include<iostream>
#define arr_length(arr) (sizeof(arr) / sizeof(arr[0]))
using namespace std;
//1. 定义两个指针, 第一指针指向数组的头部,第二个指向数组的尾部, 判断这两个指针的值
//第一指针判断是否是偶数,第二个指针是否是奇数,如果成立, 则交换位置
void order(int arr[], int len) {
if(arr == NULL || len <= 0) {
return ;
}
int *begin = arr;
int *end = &arr[len - 1];
while(begin < end){
//begin从前找偶数
while(begin < end && (*begin & 0x1) != 0) {
begin ++;
}
//end从后找奇数
while(begin < end && (*end & 0x1) == 0){
end --;
}
if(begin < end){
//交换位置
*begin = (*begin) ^ (*end);
*end = (*begin) ^ (*end);
*begin = (*begin) ^ (*end);
}
}
}
//上面第一种写法是没有问题的. 但是 面试官如果该题目(比如改成从小到大排序,能被3整除的放在不能被3整除的前面...),
//则题目需要中while中的判断是需要修改的, 其实面试官想要 面试人 给出一个<模式>,"把已有的解决方案扩展到同类问题上"
//2.传一个回调函数
void reorder(int arr[], int len, bool (*callback)(int)){
if(arr == NULL || len <= 0) {
return ;
}
int *begin = arr;
int *end = &arr[len - 1];
while(begin < end){
//begin从前找偶数
while(begin < end && !callback(*begin)) {
begin ++;
}
//end从后找奇数
while(begin < end && callback(*begin)){
end --;
}
if(begin < end){
//交换位置
*begin = (*begin) ^ (*end);
*end = (*begin) ^ (*end);
*begin = (*begin) ^ (*end);
}
}
}
//2.判断是否是偶数 --具体操作
bool isEvent(int n){
return (n & 0x1) == 0;
}
//2.统一的调用接口
void reorder_event(int arr[], int len){
reorder(arr, len, isEvent);
//后面可以添加其他的操作
}
//输出
int print_arr(int *arr, int len){
for(int i = 0; i < len; i++){
printf("%d ", arr[i]);
}printf("\n");
}
int main(void){
//1.第一种方式
int arr[7] = {1,2,3,4,5,6,7};
int len = arr_length(arr);
order(arr, len);
print_arr(arr, len);
//2.第二种方式
reorder_event(arr, len);
print_arr(arr, len);
return 0;
}
7.求链表中倒数第k个结点 – 面试题15
/*
求链表中倒数第k个结点
-------------------------------
思想一: 因为是倒数的, 所以从后来前遍历即可, 但是单链表中不能从后来前遍历,所以要从头结点到n-k+1处 就是倒数k的结点
需要遍历链表两次,不是最好的解法
-------------------------------
思想二: 如果实现遍历一次链表就能找出倒数k的结点,可以定义两个指针,第一指针先走
第一指针从头结点开始- 一直遍历到k处[从1到n 如果是从0开始,则遍历到k-1出] 后 第二个指针再从头结点 开始遍历 -- 之后两个结点同时遍历链表
当第一结点走到链表尾的时候,第二个结点就是倒数第k个结点
*/
#include<iostream>
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct Node{
ElemType data;
struct Node *next;
} Node;
typedef struct Node *LinkList;
//查找方法 结果用node返回 -- index 不能小于0 也不能大于链表长度
Status find_to_tail(LinkList p_head, int index, LinkList *node){
if(index < 0 || p_head == NULL){
return 0;
}
LinkList p_first = p_head;
LinkList p_last = NULL;
for(int i = 0; i < index; i++){
p_first = p_first->next;
if(p_first == NULL){
printf("查找位置不正确\n");
return 0;
}
}
p_last = p_head;
while(p_first != NULL){
p_first = p_first->next;
p_last = p_last->next;
}
(*node) = p_last;
return 1;
}
//遍历链表
void list_traverse(LinkList p_head){
if(p_head == NULL){
return;
}
LinkList p = p_head->next;
while(p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//初始化链表 -- 生成10个结点
void init_list(LinkList *p_head){
if(p_head == NULL){
return;
}
int num = 10;
LinkList p, new_node;
p = *(p_head);
while(num > 0){
new_node = new Node;
new_node->data = num;
p->next = new_node;
p = new_node;
num --;
}
p->next = NULL;
}
int main(void){
LinkList List, node;
init_list(&List);
int option = 1;
printf("\n 1. 遍历\n 2. 查找\n 0. 退出\n");
while(1){
scanf("%d", &option);
switch(option){
case 1:
list_traverse(List);
break;
case 2:
printf("倒数查找请输入查找位置\n");
scanf("%d", &option);
option = find_to_tail(List, option, &node);
if(option){
printf("%d \n", node->data);
}
break;
case 0:
return 0;
default:
printf("\n 1. 遍历\n 2. 查找\n 0. 退出\n");
break;
}
}
return 0;
}
8.翻转链表 – 面试题16
/*
翻转链表
------------------
题目: 定义一个函数,输入一个链表的头结点, 翻转链表并输出翻转后链表的头结点
------------------
思想: 利用3个指针, 分别指向当前遍历的结点,它的前一个结点, 它的后一个结点
-----------------
list_reverse()实现
*/
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct Node{
ElemType data;
struct Node *next;
} Node;
typedef struct Node *LinkList;
//翻转链表函数 用root 返回翻转后的头结点
Status list_reverse(LinkList *p_head, LinkList *root){
if(p_head == NULL){
printf("参数不合法");
return 0;
}
LinkList p_first = NULL;
LinkList p_current = (*p_head)->next; //头结点
LinkList p_last = NULL;
while(p_current != NULL){
p_last = p_current->next;
p_current->next = p_first;
if(p_last == NULL){
(*root) = p_current;
(*p_head) = (LinkList) malloc(sizeof(Node));
(*p_head)->next = p_current;
return 1;
}
p_first = p_current;
p_current = p_last;
}
}
//遍历链表
void list_traverse(LinkList p_head){
if(p_head->next == NULL){
return;
}
LinkList p = p_head->next;
while(p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//初始化链表 -- 生成10个结点
void init_list(LinkList *p_head){
if(p_head == NULL){
return;
}
int num = 10;
LinkList p, new_node;
*p_head = new Node; //定义一个头结点
p = *p_head;
while(num > 0){
new_node = new Node;
new_node->data = num;
p->next = new_node;
p = new_node;
num --;
}
p->next = NULL;
}
int main(void){
LinkList List, node;
init_list(&List);
int option = 1;
printf("\n 1. 遍历\n 2. 翻转链表\n 0. 退出\n");
while(1){
scanf("%d", &option);
switch(option){
case 1:
list_traverse(List);
break;
case 2:
printf("翻转链表之后的值:\n");
option = list_reverse(&List, &node);
if(option){
printf("%d \n", node->data);
}
break;
case 0:
return 0;
default:
printf("\n 1. 遍历\n 2. 查找\n 0. 退出\n");
break;
}
}
return 0;
}
9.合并两个链表 – 面试题17
/*
合并两个排序的链表
--------------
合并两个已经有序的链表--生成一个新的链表
结果是按照有序的结果(递增排序)
--------------
因为是产生了一个新的链表, 所以 可以使用递归的思想,
当第一个链表小于第二个链表, 就将第一链表的头结点赋给新的链表, 否则,第二个链表的头结点赋值给新的链表 ---一直这样
merge()函数实现
-------------
如果不产生, 可以使用借助一个指针, 标记头结点小的next指针
*/
#include<iostream>
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct Node{
ElemType data;
struct Node *next;
} Node;
typedef struct Node *LinkList;
//合并链表 -- 结果返回到 p_head3
LinkList merge(LinkList p_head1, LinkList p_head2){
//判断两个链表是否为null, 如果是null, 则返回 另一个链表
if(p_head1 == NULL){
return p_head2;
} else if(p_head2 == NULL){
return p_head1;
}
LinkList p_head3 = NULL;
LinkList p1 = p_head1, p2 = p_head2;
if(p1->data > p2->data){
p_head3 = p2;
p_head3->next = merge(p1, p2->next);
}else{
p_head3 = p1;
p_head3->next = merge(p1->next, p2);
}
return p_head3;
}
//遍历链表
void list_traverse(LinkList p_head){
if(p_head == NULL){
return;
}
LinkList p = p_head->next;
while(p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//初始化第一个链表 -- 生成10个结点
void init_list(LinkList *p_head){
if(p_head == NULL){
return;
}
int num = 10;
LinkList p, new_node;
p = *(p_head);
for(int i = 0; i < num; i++){
new_node = new Node;
new_node->data = i;
p->next = new_node;
p = new_node;
}
p->next = NULL;
}
//初始化第二个链表 -- 生成10个结点
void init_list2(LinkList *p_head){
if(p_head == NULL){
return;
}
int num = 20;
LinkList p, new_node;
p = *(p_head);
for(int i = 0; i < num; i += 2){
new_node = new Node;
new_node->data = i;
p->next = new_node;
p = new_node;
}
p->next = NULL;
}
int main(void){
LinkList List1, List2, List3, node;
init_list(&List1);
init_list2(&List2);
printf("遍历链表1的结果: \n");
list_traverse(List1);
printf("遍历链表2的结果: \n");
list_traverse(List2);
printf("遍历合并链表后的结果: \n");
list_traverse(merge(List1->next, List2->next));
return 0;
}
10.数组中超过一半的数字 – 面试题29
/*
数组中,有一个数字出现的次数超过数组长度的一半,找出来.
---------------------
1. 因为数字出现的次数会超过数组长度的一半,所以给数组排序之后, 中间的数就是超出数组一半的数
2. 和一相同, 采用一个计数器, 一个参考值, 如果相同,计数器加一,否则计数器减一,最后计数器大于1的那个数就是要找的数
--------------------
采用第二种方式
*/
#include<iostream>
using namespace std;
//判断数组的合法性
bool check_array(int *arr, int length){
if(arr == NULL || length <= 0){
return false;
}
return true;
}
//找出超过一半的数字
int more_half_num(int *num, int length){
if(!check_array(num, length)){
return 0;
}
int result = num[0]; //参考值
int times = 1; //计数器
for(int i = 1; i < length; i++){
if(result == num[i]){
times++;
}else if(result != num[i]){
times--;
}
if(times == 0){
result = num[i];
times = 1;
}
}
return result;
}
int main(void){
int arr[9] = {1,2,3,2,2,2,5,4,2};
int res = more_half_num(arr, 9);
printf("数组中出现次数最多的元素是: %d ", res);
return 0;
}
11.连续子数组中的最大和 – 面试题31
/*
连续子数组中的最大和
输入一个整形的数组,其中有整数也有负数,求数组中一个或者连续的多个整数组成的一个子数组.时间复杂度是O(n)
--------------------
1.采用分析数组规律, 当累加数组中出现负数,则从后一位开始计算,每一次累加的数和上次累加的数比较,将最大值保留起来
*/
#include<iostream>
using namespace std;
//求连续子数组中的最大和
int sub_array_sum(int *arr, int length){
if(arr == NULL || length <= 0){
return 0;
}
int current_sum = 0; //每次累加的数,存放位置
int current_sum_max = 0; //存放最大值
for(int i = 0; i < length; i++){
if(current_sum <= 0){ //前面的数组元素之和小于0 则从当前元素开始计算
current_sum = arr[i];
}else{
current_sum += arr[i]; //累加计数
}
if(current_sum > current_sum_max){
current_sum_max = current_sum; //存放最大值
}
}
return current_sum_max;
}
int main(void){
int arr[8] = {1,-2,3,10,-4,7,2,-5} ;
int res = sub_array_sum(arr, 8);
printf("连续子数组中的最大和是: %d ", res);
return 0;
}
12.求最小于k个数 – 面试题30
//求最小于k个数-- 基于快排的思想
int partition(int arr[], int start, int end){
int low = start;
int high = end;
int temp = arr[low];
while(high > low){
while(high > low && arr[high] >= temp){
high --;
}
arr[low] = arr[high];
while(high > low && arr[low] <= temp){
low++;
}
arr[high] = arr[low];
}
arr[low] = temp;
return low;
}
void get_last_num(int arr[], int len, int num){
if(NULL == arr || len <= 0 || num <= 0){
return;
}
int start = 0;
int end = len - 1;
int index = partition(arr, start, end);
while(index != num - 1){//index== num-1表示前面num个是最小值
if(index > num - 1){
end = index - 1;
}
else{
start = index + 1;
}
index = partition(arr, start, end);
}
for(int i = 0; i < num; i++){
printf("%d ", arr[i]);
}
}
13. 句子翻转 – I am student 反转为 student am I
思想, 先对单词翻转, 最后在整体翻转
#include<iostream>
#include<string.h>
using namespace std;
//字符串的翻转 -- I am student 反转为 student am I
/*
思想, 先对单词翻转, 最后在整体翻转
*/
void reve_change(char *start, char *end) {
if(start == NULL || end == NULL){
return ;
}
char temp;
while(start < end){
temp = *start;
*start = *end;
*end = temp;
start ++;
end --;
}
}
char *reve_sentence(char *str){
if(str == NULL || strlen(str) == 0){
return str;
}
int len = strlen(str);
char *pre = str;
char *p_cur;
p_cur = strchr(pre, ' ') ;
if(p_cur == NULL){
return str;
}
while(p_cur = strchr(pre, ' ')){
reve_change(pre, p_cur - 1) ;
pre = p_cur + 1;
}
p_cur = str + len - 1;
reve_change(pre, p_cur);
reve_change(str, p_cur);
return str;
}
int main(void){
char string[] = "I am a student";
cout << reve_sentence(string);
return 0;
}
14. 字符串前面n个字符放到后面 – abcdef 前三个放到后为 defabc
思想: 1. 前n个字符翻转, 2. 后面的字符翻转, 3. 整体翻转
void reve_change(char *start, char *end) {
if(start == NULL || end == NULL){
return ;
}
char temp;
while(start < end){
temp = *start;
*start = *end;
*end = temp;
start ++;
end --;
}
}
//字符串前面n个字符放到后面
char *str_reve(char *str, int n){
if(NULL == str || strlen(str) == 0){
return str;
}
int len = strlen(str);
if(n <= 0 || n >= len){
return str;
}
reve_change(str, str + n - 1);
reve_change(str + n, str + len - 1);
reve_change(str, str + len - 1);
return str;
}
int main(void){
char string[] = "I am a student";
cout << str_reve(string, 4);
return 0;
}
15. 实现一个函数,对一个正整数n,算得到1需要的最少操作次数。操作规则为:如果n为偶数,将其除以2;如果n为奇数,可以加1或减1;一直处理下去
分析: 奇数的时候加1或减1,完全取决于二进制的后两位,如果后两位是10、00那么肯定是偶数,选择除以2,如果后两位是01、11,那么选择结果会不一样的,如果是*****01,那么选择减1,如果是*****11,那么选择加1,特殊情况是就是n是3的时候,选择减1操作
//递归实现
int func(int n){
if(n == 1){
return 0;
}
if(n & 0x1) == 0){
return 1 + func(n / 2);
}
if(n == 3){
return 2;
}
if(n & 0x2){
return 1 + func(n + 1);
}else{
return 1 + func(n - 1);
}
}
//非递归实现
int func(int n){
int count = 0;
while(n > 1){
if(n % 2 == 0){
n >>= 1;
}else if(n == 3){
n --;
}else{
if(n & 0x2){
n++;
}else{
n--;
}
}
count++;
}
return count;
}
16. 消除嵌套的括号
例如 输入 (1,2,3,(2,3),(3,3)), 则输出(1,2,3,2,3,3,3)
//验证字符串是否是合法的
bool is_valid(char *str) {
if(NULL == str){
return false;
}
stack<char>stack;
while('\0' != *str){
if('(' == *str){
stack.push(*str++);
}else if(')' == *str){
if(stack.empty()){
return false;
}else{
stack.pop();
str++;
}
}else{
str++;
}
}
if(stack.empty()){
return true;
}else{
return false;
}
}
//消去中间的括号
char *elem_back(char *str) {
if(NULL == str){
return str;
}
char *temp = new char[strlen(str) + 1];
char *result = temp;
*temp++ = *str++;
while('\0' != *str){
if('(' == *str || ')' == *str){
str++;
continue;
}
*temp++ = *str++;
}
*temp++ = ')';
*temp = '\0';
return result;
}
int main(void){
char arr_temp[] = "(1,2,3,(2,3),(3,3))";
if(is_valid(arr_temp)){
cout << elem_back(arr_temp);
}
return 0;
}
17. 求两个有序数组的交集
时间复杂度为O(N+M)
先判断两个数组的首元素是否相等, 如果相等则输出, 不相等,小的则相应的数组指针后移,直到坐标超过数组的范围
//两个有序数组的交集
void inter_array(int arr1[], int arr1_len, int arr2[], int arr2_len) {
if(NULL == arr1 || NULL == arr2 || 0 >= arr1_len || 0 >= arr2_len){
return;
}
int index_arr1, index_arr2;
index_arr1 = index_arr2 = 0;
while(index_arr1 < arr1_len && index_arr2 < arr2_len){
if(arr1[index_arr1] == arr2[index_arr2]){
cout << arr1[index_arr1] << " ";
index_arr1 ++;
index_arr2 ++;
}else if(arr1[index_arr1] < arr2[index_arr2]){
index_arr1 ++;
}else{
index_arr2 ++;
}
}
}
18. 约瑟夫环
int huan(int arr[], int len, int k){
int count = 0;
int i = 0;
int len_of_o = len;
while(len_of_o != 0){
if(arr[i % len] != -1) {
count ++;
}
if(count == 3){
arr[i % len] = -1;
len_of_o --;
count = 0;
}else{
i++;
}
if(len_of_o == 1){
if(arr[i % len] != -1) {
return (i % len);
}
}
}
}
int main(void){
int arr6[7] = {0,0,0,0,0,0,0};
cout << huan(arr6, 7,3);
return 0;
}
//php
//约瑟夫环
function ring($arr, $m){
if(empty($arr) || 0 == $m){
return -1;
}
$len = count($arr);
$index = 0;
while($len != 1){
$index ++;
$header = array_shift($arr);
if($index % $m != 0){
array_push($arr, $header);
}else{
$len --;
}
}
return $arr[0];
}
$arr = [1,2,3,4,5,6];
var_dump(ring($arr, 3));