Как найти перемену знака в массиве

0 / 0 / 0

Регистрация: 22.09.2012

Сообщений: 19

1

Алгоритмы (найти последнюю перемену знака в массиве)

10.05.2013, 21:34. Показов 543. Ответов 7


Студворк — интернет-сервис помощи студентам

Подскажите,как найти последнюю перемену знака в массиве,без использования циклов и рекурсии.



0



244 / 245 / 38

Регистрация: 08.04.2013

Сообщений: 927

10.05.2013, 21:38

2

Fissil, что значит “перемена знака в массиве”?



0



0 / 0 / 0

Регистрация: 22.09.2012

Сообщений: 19

10.05.2013, 21:42

 [ТС]

3

ну перемена знака,когда после положительного элемента идет отрицательный,либо наоборот



0



Genn55

413 / 250 / 118

Регистрация: 26.12.2012

Сообщений: 786

10.05.2013, 22:49

4

Наверное как то так

C++
1
2
3
4
5
6
7
8
if(((((A[i]>0)&&(A[i+1]>0)))||(((A[i]<0)&& (A[i+1]<0))))&&(A[i]!=0))
        {
            //что то делать
        }
        else;
        {
            //знак поменялся
        }



0



244 / 245 / 38

Регистрация: 08.04.2013

Сообщений: 927

10.05.2013, 23:19

5

Genn55, и как это решает задачу?



0



413 / 250 / 118

Регистрация: 26.12.2012

Сообщений: 786

10.05.2013, 23:26

6

Извиняюсь.Проверил.Плохо.



0



2020 / 1619 / 489

Регистрация: 31.05.2009

Сообщений: 3,005

10.05.2013, 23:38

7

Цитата
Сообщение от Fissil
Посмотреть сообщение

Подскажите,как найти последнюю перемену знака в массиве,без использования циклов и рекурсии.

Каков бы ни был алгоритм элементы в любом случае нужно как-то перебирать Или вы имеете в виду алгоритм из STL? В таком случае, учитывая что нужно найти последнюю пару соседних элементов с разными знаками: std::adjacent_find + свой предикат + reverse_iterator.



0



Genn55

413 / 250 / 118

Регистрация: 26.12.2012

Сообщений: 786

11.05.2013, 02:51

8

Как то так.С 0 добавить условие,если нужно.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
 using namespace std;
 
int main()
{
    const int size=10;
    int A[size]={-1,5,-6,-8,3,7,-7,-6,4,3};
 
     cout<<" array A:"<<endl;
    for(int i=0;i!=size;i++)
 
        cout<<A[i]<<" ";
        cout<<"n";
 
 int countB=0,countC=0,i;
     for( i=0;i<size;i++)
        {
         countB=A[i-1];
     countC=A[i];
        }
if (((countB>0)&&(countC>0))||((countB<0)&&(countC<0)))
cout<<"   no"<<"n";
else
cout<<"   yes "<<"n";
 
    return 0;
}

Добавлено через 2 часа 5 минут
Или так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cstdlib>
#include <ctime>
 using namespace std;
 
int main()
{
    const int size=10;
    int A[size];
 
    srand(int(time(0)));
    cout<<"array A:"<<endl;
    for(int i=0;i!=size;i++)
    {
        A[i]=5-rand()%10;
        cout<<A[i]<<" ";
    }
    cout<<endl;
 
    int countB=0,countC=0,i;
       for(i=size;i>=1;i--)
{
if ((i-1)==0)
break;
        countB=A[i-1];
        countC=A[i];
if (((countB>0)&&(countC<0))||((countB<0)&&(countC>0)))
break;
}
cout <<"  pos "<< i<<"n";
    return 0;
}



0



Самый простой, да и надежный путь – наивное решение со счетчиком и циклом. Но это не наш метод. Для начала текст, потом код.

Возьмем вот такой массив как пример: [-3, -4, 5, -5, 0, 3, -3] и оставим вместо самих чисел только их знак: 1 для положительных, -1 для отрицательных: [-1, -1, 1, -1, 1, 1, -1]. Теперь будем брать последовательно два рядом стоящих числа (их знака). Вот так будет выглядеть последовательность:

-3, -4 (-1, -1); 
-4, 5 (-1, 1); 
5, -5 (1, -1); 
-5, 0 (-1, 1); 
0, 3 (1, 1); 
3, -3 (1, -1). 

Таких пар чисел будет ровно len(list) - 1, т.е. длина списка минус 1. Представьте, что все числа положительны. Тогда сумма всех пар знаков (т.е. единиц) будет равна (len(list) - 1) * 2. Хорошо, если вы не просто поверите на слово, а проверите данный тезис. Каждая пара чисел с разными знаками уменьшает сумму на 2. Обозначим сумму этих пар знаков как summ и исходя из всего вышесказанного количество смен знаков будет равно ((len(list) - 1) * 2 - summ) / 2. Распишем сумму как сумму элементов массива с индексами:
summ := |a0 + a1| + |a1 + a2| + |a2 + a3| + |a3 + a4| + |a4 + a5| + |a5 + a6|, где |...| – это модуль числа. На этом в общем-то и все:

import random
# Все, что касается знаков спихиваем на библиотеку
# Ибо можно попасть на всякие нехорошие вещи типа -0.0, nan, -nan и т.д.
# Однако copysign вычисляет в процессе арктангенс(!!!) от числа и нельзя сказать, что
# это очень быстро. Для ультра быстроты можно поиграть с битовыми сдвигами
from math import copysign

LIST_LEN = 7

target_list = [random.randint(-15, 15) for _ in range(LIST_LEN)]
only_ones_list = [copysign(1, element) for element in target_list]

summ = 0
for i in range(len(only_ones_list) - 1):
    summ += abs(only_ones_list[i] + only_ones_list[i + 1])

sign_change_count = ((len(only_ones_list) - 1) * 2 - summ) / 2

print(target_list)
print(only_ones_list)
print(sign_change_count)

>>> [-6, 12, -3, -11, -12, -13, 7]
>>> [-1, 1, -1, -1, -1, -1, 1]
>>> 3.0

Список из знаков можно не составлять, конечно же, а сразу пройти по исходному.

Теперь самое сложное – чем данное может быть полезным. Во-первых, никаких рассуждений о знаковости нуля или nan или еще чего угодно. Мы используем стандартную функцию и не паримся. Теоретически можно обойтись совсем без условных операторов (внутри abs и copysign) – получение знака и модуль числа можно попробовать вычислить хитрыми битовыми операциями. Также теоретически сложение быстрее, чем умножение, однако разница будет заметна на больших массивах.

#pragma hdrstop
#pragma argsused
#include <iostream.h>
#include <conio.h>
 
int main(int argc, char* argv[])
{
  int mas [10];
  char ch;
  int mesto[10];
  int count=0;
 
  for (int i=0; i<10; i++)
   { cin>>mas[i]; }
 
   if   (mas[0]>=0)  ch = '+';
   else              ch = '-';
 
  for(int i=0; i<10; i++)
   {
     if (mas[i]>=0)
      {
         if (ch=='-')
          { ch='+';
            mesto[count]=i;
            count++;
          }
      }
     else
      {
          if (ch=='+')
          { ch='-';
            mesto[count]=i;
            count++;
          }
      }
   }
 
 cout<<"a sign changes after the ";
   for (int i=0; i<count; i++)
    {
      if (i!=0) cout<<","<<mesto[i];
      else      cout<<mesto[i];
    }
 cout<<" array cell(s)"<<"n";
 cout<<"a sign changes "<<count<<" times";
 
 getch();
}


Форум программистов Vingrad

Модераторы: Poseidon

Поиск:

Ответ в темуСоздание новой темы
Создание опроса
> [Java] Cмена знака в последовательности чисел 

:(

   

Опции темы

Merhaba
Дата 13.5.2011, 22:52 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 93
Регистрация: 23.4.2011

Репутация: нет
Всего: нет

Добрый Вечер!!!
Помогите Пожалуйста наисать программу которая будет считать, сколько раз в последовательности чисел меняется знак  (например, в последовательности –5, –2, 9, 1, 0, 4, –3 знак меняется дважды: с минуса на плюс, затем с плюса на минус).
Без использования массива! 

Код

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
    Scanner con = new Scanner (System.in);
           int N;
    System.out.println("Здравствуйте, уважаемый пользователь!");
    System.out.print ("Введите количество чиcел N (N > 0) = ");
    N=con.nextInt();
    for (int i = 0; i < N; i++) {
       System.out.print("Введите число № " + i + ": ");
       d = con.nextInt();
  }

PM MAIL   Вверх
frikey
Дата 14.5.2011, 07:06 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Senior Sys Engineer

Профиль
Группа: Участник
Сообщений: 31
Регистрация: 3.10.2008
Где: Russia, Samara

Репутация: нет
Всего: нет

Пожалуйста:

Код

public class Main {

    public static void main(String[] args) {
        Scanner con = new Scanner(System.in);

        System.out.println("Здравствуйте, уважаемый пользователь!");
        System.out.print("Введите количество чиcел N, (N > 0) = ");

        int total = con.nextInt();
        int signChangeCounter = 0;

        boolean prevIsNegative = false;

        for (int i = 0; i < total; i++) {
            System.out.print("Введите число № " + (i + 1) + ": ");
            int parsed = con.nextInt();

            boolean curIsNegative = parsed < 0;

            if (i == 0) {
                prevIsNegative = curIsNegative;
            } else {
                if (prevIsNegative != curIsNegative) {
                    signChangeCounter++;
                }
            }
        }

        System.out.println("Количество смен знака в последовательности: " + signChangeCounter);
    }
}

PM MAIL WWW ICQ Skype GTalk   Вверх
Merhaba
Дата 15.5.2011, 07:05 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 93
Регистрация: 23.4.2011

Репутация: нет
Всего: нет

frikey
Спасибо Вам Большое!!!

PM MAIL   Вверх
Merhaba
Дата 15.5.2011, 10:24 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 93
Регистрация: 23.4.2011

Репутация: нет
Всего: нет

frikey
Почему-то неверно считает, когда ввёл последовательнсть из примера:

Код

Введите количество чиcел N, (N > 0) = 7
Введите число № 1: -5
Введите число № 2: -2
Введите число № 3: 9
Введите число № 4: 1
Введите число № 5: 0
Введите число № 6: 4
Введите число № 7: -3
Количество смен знака в последовательности: 4
BUILD SUCCESSFUL (total time: 39 seconds)

(например, в последовательности –5, –2, 9, 1, 0, 4, –3 знак меняется дважды: с минуса на плюс, затем с плюса на минус).

PM MAIL   Вверх
frikey
Дата 15.5.2011, 19:21 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Senior Sys Engineer

Профиль
Группа: Участник
Сообщений: 31
Регистрация: 3.10.2008
Где: Russia, Samara

Репутация: нет
Всего: нет

Прошу прощения. Глупейшая ошибка  smile

Вот корректный код:

Код

public class SignsReader {

    public static void main(String[] args) {
        Scanner con = new Scanner(System.in);

        System.out.println("Здравствуйте, уважаемый пользователь!");
        System.out.print("Введите количество чиcел N, (N > 0) = ");

        int total = con.nextInt();
        int signChangeCounter = 0;

        boolean prevIsNegative = false;

        for (int i = 0; i < total; i++) {
            System.out.print("Введите число № " + (i + 1) + ": ");
            int parsed = con.nextInt();

            boolean curIsNegative = parsed < 0;

            if (i != 0) {
                if (prevIsNegative != curIsNegative) {
                    prevIsNegative = curIsNegative;
                    signChangeCounter++;
                }
            } else {
                prevIsNegative = curIsNegative;
            }
        }

        System.out.println("Количество смен знака в последовательности: " + signChangeCounter);
    }
}

PM MAIL WWW ICQ Skype GTalk   Вверх
Merhaba
Дата 15.5.2011, 21:46 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 93
Регистрация: 23.4.2011

Репутация: нет
Всего: нет

frikey
Опишите Пожалуйста алгоритм, который реализуется вот в этом блоке:

Код

boolean curIsNegative = parsed < 0;

            if (i != 0) {
                if (prevIsNegative != curIsNegative) {
                    prevIsNegative = curIsNegative;
                    signChangeCounter++;
                }
            } else {
                prevIsNegative = curIsNegative;
            }
        }

PM MAIL   Вверх
frikey
Дата 16.5.2011, 05:38 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Senior Sys Engineer

Профиль
Группа: Участник
Сообщений: 31
Регистрация: 3.10.2008
Где: Russia, Samara

Репутация: нет
Всего: нет

Суть в следующем:
Есть два флага curIsNegative и prevIsNegative. Первый указывает на то является ли текущее введенное число отрицательным, второй, соответственно, указывает на отрицательность предыдущего введенного значения. На первой итерации цикла выполняется операция prevIsNegative = curIsNegative, по скольку предыдущих значений у нас ещё нет. На последующих итерациях происходит сравнение флагов и в случае их неравенства, это и означает что знак был изменен. А если знак был изменен, то, происходит инкремент счетчика.

PM MAIL WWW ICQ Skype GTalk   Вверх
Merhaba
Дата 16.5.2011, 06:29 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 93
Регистрация: 23.4.2011

Репутация: нет
Всего: нет

frikey
Спасибо Вам большое за Помощь!!!
Если Вам не сложно, помогите Пожалуйста решить ещё одну задачу, выложенную мной в этом разделе!

PM MAIL   Вверх



















Ответ в темуСоздание новой темы
Создание опроса
Правила форума “Центр помощи”

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!

  • Название темы должно отражать её суть! (Не следует добавлять туда слова “помогите”, “срочно” и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например “школьная задача”, “задача из учебника” и т.п.), не нужно указывать ее сложность (“простая задача”, “легкий вопрос” и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку “Код”). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик – один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой “Пометить как решённый”, которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 

0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »

Мне нужно написать функцию, которая берет элементы массива и меняет знак (например, 3 –> -3 или -3 –> 3). Дело в том, что мне нужно изменить все значения, кроме первых трех целых чисел в массиве, а затем отобразить весь массив с неизмененными и измененными значениями.
Вот мой код

#include<stdio.h>
#include<stdlib.h>

void change_sign(int x[], int n)
{
    int *ptr[n];
    int i;
    for(i = 0; i < n; i++)
    {
        ptr[i] = &x[i+3];
    }
    for(i = 0; i < n; i++)
    {        
        x[i] = *ptr[i] * (-1);
        printf("%dn", x[i]);
    }
}

int main()
{

int arr [10] = {-5, 13, -2, 5, 8, -54, 82, -4, 9, -43};

change_sign(arr, 10);

return 0;    
}

Это, очевидно, не работает, оно показывает только измененные числа и некоторые случайные числа в конце.
Любая помощь будет принята с благодарностью.

Перейти к ответу
Данный вопрос помечен как решенный


Ответы
2

Попробуй это

#include<stdio.h>
#include<stdlib.h>

void change_sign(int x[], int n)
{

    int i;
    for(i = 0; i < n; i++)
    {
        if (i>2)
        x[i] = -x[i];

        printf("%dn", x[i]);
    }
}

int main()
{

int arr [10] = {-5, 13, -2, 5, 8, -54, 82, -4, 9, -43};

change_sign(arr, 10);

return 0;    
}

Ваша ошибка связана с выходом за пределы

Если вы не хотите использовать указатель, попробуйте что-то вроде

void change_sign(int x[], int n)
{
    for(int i = 3; i < n; i++)
    {
        x[i] = -x[i] ;
    }
}

Другие вопросы по теме

Добавить комментарий